diff --git a/.cargo/config.toml b/.cargo/config.toml index afcc2073c6..bbfc28a440 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,9 +1,3 @@ -# See https://github.com/bevyengine/bevy/blob/3a2a68852c0a1298c0678a47adc59adebe259a6f/.cargo/config_fast_builds - -# We can't use LLD because it's not stable. - [build] -# Speeds up compilation by using shared artifacts between libraries. We -# don't use a Cargo workspace since that causes issues with Cargo chef. -target-dir = "./target" +rustflags = ["--cfg", "tokio_unstable"] diff --git a/.dockerignore b/.dockerignore index 45a3b9079d..fe2aaff472 100644 --- a/.dockerignore +++ b/.dockerignore @@ -19,18 +19,7 @@ **/dist/ **/node_modules/ **/target -!frontend/apps/hub/dist -# Site -site/public/rss/ -!site/public/rss/.gitkeep - -site/src/generated/ -!site/src/generated/errorPages.json -!site/src/generated/apiPages.json -!site/src/generated/meta.json - -# Icons -frontend/packages/icons/src/* -!frontend/packages/icons/src/package.json +# Frontend +!frontend/dist/ diff --git a/.editorconfig b/.editorconfig old mode 100755 new mode 100644 index 3b37cef992..e993f9c3ce --- a/.editorconfig +++ b/.editorconfig @@ -7,4 +7,4 @@ indent_size = 4 [*.yaml] indent_style = space -indent_size = 2 +indent_size = 2 \ No newline at end of file diff --git a/.gitattributes b/.gitattributes index 780ee1d269..1175647a14 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7,15 +7,15 @@ *.tar.gz filter=lfs diff=lfs merge=lfs -text *.tgz filter=lfs diff=lfs merge=lfs -text -# Prevent from counting in the language statistics -# -# https://github.com/github-linguist/linguist/blob/559a6426942abcae16b6d6b328147476432bf6cb/docs/overrides.md#vendored-code -sdks/api/** linguist-generated=true **/Cargo.lock linguist-generated=true +# Prevent from counting in the language statistics +out/** linguist-generated=true +sdks/api/** linguist-generated=true sdks/api/fern/** linguist-generated=false site/public/llms.txt linguist-generated=true site/public/llms-full.txt linguist-generated=true site/public/docs/**/*.md linguist-generated=true +**/Cargo.lock linguist-generated=true diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 0783cde244..0000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -name: Bug report -about: Report something wrong with Rivet -labels: bug ---- - -## Environment - -- [ ] Rivet Cloud - - Game ID: [please provide] -- [ ] Rivet self-hosted local - - Version/commit: [please provide] -- [ ] Rivet self-hosted cluster - - Version/commit: [please provide] - -## Description - - - - - -## Steps to reproduce - -1. -2. -3. - -## Workarounds - - - -## More information diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 4d12d87696..0000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: Feature proposal -about: Propose a feature -labels: enhancement ---- - -## Description - - - - - -## Alternatives solutions - - - -## Prior art - - diff --git a/.github/actions/pre-init-distributed/action.yaml b/.github/actions/pre-init-distributed/action.yaml deleted file mode 100644 index 77b8002bca..0000000000 --- a/.github/actions/pre-init-distributed/action.yaml +++ /dev/null @@ -1,82 +0,0 @@ -name: pre-init-distributed -description: Set up Nix and Bolt - -# TODO: Composite actions don't support defaults -# defaults: -# run: -# # Enable fail-fast behavior -# shell: bash -e {0} - -inputs: - DOCKER_CI_ACCESS_TOKEN: - required: true - -runs: - using: composite - - steps: - # MARK: Cache - - name: Nix Cache - uses: actions/cache@v3.3.1 - with: - key: ${{ runner.os }}-nix-${{ hashfiles('./shell.nix', './nix/**/*.nix') }} - path: ${{ env.store }} - restore-keys: | - ${{ runner.os }}-nix-${{ hashfiles('./shell.nix', './nix/**/*.nix') }} - ${{ runner.os }}-nix- - - # Cache generated Bolt files in order to prevent needless rebuilding - - name: Bolt Cache - uses: actions/cache@v3 - with: - key: ${{ runner.os }}-bolt-gen - path: | - packages/services/region/ops/config-get/gen - - # MARK: Nix - - uses: cachix/install-nix-action@v22 - with: - nix_path: nixpkgs=channel:nixos-23.05 - extra_nix_config: "store = ${{ env.store }}\n" - - # Build initial shell, all future calls to nix-shell will be fast - - name: Build Shell - shell: bash -e {0} - run: nix-shell --pure --run "echo 'Built shell'" - - # MARK: Bolt - - name: Write Configs - shell: bash -e {0} - run: | - cat << 'EOF' > Bolt.local.toml - namespace = "ci" - EOF - - cat << 'EOF' > namespaces/ci.toml - # To appease bolt; these won't be used - [dns.domain] - main = "" - cdn = "" - job = "" - - [cluster.distributed] - - [docker] - authenticate_all_docker_hub_pulls = false - repository = "docker.io/rivetgg/" - EOF - - cat << EOF > secrets/ci.toml - [docker.registry."docker.io".write] - username = "rivetggci" - password = "${{ inputs.DOCKER_CI_ACCESS_TOKEN }}" - EOF - - # Delete old Bolt binaries in order to fall back to the Nix-built binary - - name: Remove Old Bolt Builds - shell: bash -e {0} - run: rm -f target/debug/bolt target/release/bolt - - - name: Generate Bolt Config - shell: bash -e {0} - run: nix-shell --pure --run "bolt config generate ci" diff --git a/.github/actions/pre-init/action.yaml b/.github/actions/pre-init/action.yaml deleted file mode 100644 index bcec2fd3f0..0000000000 --- a/.github/actions/pre-init/action.yaml +++ /dev/null @@ -1,51 +0,0 @@ -name: pre-init -description: Set up Nix and Bolt - -# TODO: Composite actions don't support defaults -# defaults: -# run: -# # Enable fail-fast behavior -# shell: bash -e {0} - -inputs: - OP_SERVICE_ACCOUNT_TOKEN: - required: true - -runs: - using: composite - - steps: - # MARK: Cache - - name: Nix Cache - uses: actions/cache@v3.3.1 - with: - key: ${{ runner.os }}-nix-${{ hashfiles('./shell.nix', './nix/**/*.nix') }} - path: ${{ env.store }} - restore-keys: | - ${{ runner.os }}-nix-${{ hashfiles('./shell.nix', './nix/**/*.nix') }} - ${{ runner.os }}-nix- - - # MARK: Nix - - uses: cachix/install-nix-action@v22 - with: - nix_path: nixpkgs=channel:nixos-23.05 - extra_nix_config: "store = ${{ env.store }}\n" - - # Build initial shell, all future calls to nix-shell will be fast - - name: Build Shell - shell: bash -e {0} - run: nix-shell --pure --run "echo 'Built shell'" - - # MARK: Bolt - - name: Pull Config - shell: bash -e {0} - env: - OP_SERVICE_ACCOUNT_TOKEN: ${{ inputs.OP_SERVICE_ACCOUNT_TOKEN }} - # Cannot use --pure `https://github.com/NixOS/nixpkgs/issues/66716` - run: | - nix-shell --run "bolt config pull -y ci --op-namespace-path 'op://Engineering/ice6g6zdnag4lxl5d3dcs7jj64/config' --op-secrets-path 'op://Engineering/ice6g6zdnag4lxl5d3dcs7jj64/secrets'" - - # Delete old Bolt binaries in order to fall back to the Nix-built binary - - name: Remove Old Bolt Builds - shell: bash -e {0} - run: rm -f target/debug/bolt target/release/bolt diff --git a/.github/media/1password_context_menu.png b/.github/media/1password_context_menu.png deleted file mode 100644 index 9f04a5b6fd..0000000000 Binary files a/.github/media/1password_context_menu.png and /dev/null differ diff --git a/.github/media/1password_create_item.png b/.github/media/1password_create_item.png deleted file mode 100644 index ffb3e10363..0000000000 Binary files a/.github/media/1password_create_item.png and /dev/null differ diff --git a/.github/media/architecture.png b/.github/media/architecture.png deleted file mode 100644 index d9d543758e..0000000000 Binary files a/.github/media/architecture.png and /dev/null differ diff --git a/.github/media/code.png b/.github/media/code.png deleted file mode 100644 index 3828d6600e..0000000000 Binary files a/.github/media/code.png and /dev/null differ diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index b66d81ba49..0000000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,5 +0,0 @@ - - -## Changes - - diff --git a/.github/workflows/autofix.ci.yml b/.github/workflows/autofix.ci.yml deleted file mode 100644 index da21b2d5da..0000000000 --- a/.github/workflows/autofix.ci.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: "autofix.ci" - -on: - pull_request: - paths: - - frontend/** - - site/** - - sdks/actor/** - -jobs: - autofix: - name: "autofix.ci" - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: biomejs/setup-biome@v2 - with: - version: latest - - run: biome check . --fix --reporter=github - - uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c \ No newline at end of file diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index ecd27d0a55..5a3d426789 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -36,6 +36,7 @@ jobs: uses: anthropics/claude-code-action@beta with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} # Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4) # model: "claude-opus-4-20250514" diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 58d0fa2ec1..4dddae7178 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -34,6 +34,7 @@ jobs: uses: anthropics/claude-code-action@beta with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} # Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4) # model: "claude-opus-4-20250514" diff --git a/.github/workflows/deploy-proxy.yaml b/.github/workflows/deploy-proxy.yaml deleted file mode 100644 index 5b92a861a2..0000000000 --- a/.github/workflows/deploy-proxy.yaml +++ /dev/null @@ -1,31 +0,0 @@ -# Based on https://github.com/orgs/community/discussions/26323#discussioncomment-6749966 - -name: deploy-proxy - -on: - push: - branches: - - main - -defaults: - run: - # Enable fail-fast behavior - shell: bash -e {0} - -jobs: - emit: - runs-on: ubuntu-24.04 - steps: - - name: Send deploy message to EE - uses: actions/github-script@v7 - with: - # Use "Fine-grained tokens (beta)", select the target repo, give read-write access to "Content" category. - github-token: ${{ secrets.DEPLOY_PROXY_PAT }} - script: | - const result = await github.rest.repos.createDispatchEvent({ - owner: 'rivet-gg', - repo: 'rivet-ee', - event_type: 'deploy_proxy', - client_payload: { } - }); - console.log(result); diff --git a/.github/workflows/fe-pull-request.yml b/.github/workflows/fe-pull-request.yml index 1d8b66b746..5155168b2c 100644 --- a/.github/workflows/fe-pull-request.yml +++ b/.github/workflows/fe-pull-request.yml @@ -4,8 +4,7 @@ on: pull_request: paths: - frontend/** - - site/** - - sdks/actor/** + - sdks/typescript/runner/** jobs: quality: diff --git a/.github/workflows/fern.yaml b/.github/workflows/fern.yaml deleted file mode 100644 index 8d44222d78..0000000000 --- a/.github/workflows/fern.yaml +++ /dev/null @@ -1,70 +0,0 @@ -name: fern - -on: - push: - paths-ignore: - - 'frontend/**' - -defaults: - run: - # Enable fail-fast behavior - shell: bash -e {0} - -jobs: - fern-check: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - run: npm install -g fern-api - - name: Check Fern API is valid - run: ./scripts/fern/check.sh - # TODO: JS output is not deterministic - # - name: Verify generated code is up to date - # env: - # FERN_TOKEN: ${{ secrets.FERN_TOKEN }} - # run: | - # ./scripts/fern/gen.sh - # git --no-pager diff --exit-code - - fern-publish: - runs-on: ubuntu-20.04 - needs: - - fern-check - steps: - # Only run on a tagged push - - name: Check Tag - id: check-tag - run: | - if [[ ${{ github.event.ref }} =~ ^refs/tags/[0-9]+\.[0-9]+\.[0-9]+.*$ ]]; then - echo "match=true" >> $GITHUB_OUTPUT - fi - - - name: Checkout repo - if: steps.check-tag.outputs.match == 'true' - uses: actions/checkout@v4 - - - name: Publish Full - if: steps.check-tag.outputs.match == 'true' - env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - run: | - cd sdks/full/typescript - - npm config set '//registry.npmjs.org/:_authToken' "$NPM_TOKEN" - - yarn version --no-git-tag-version --new-version "${{ github.ref_name }}" - yarn pack --ignore-scripts -f archive.tgz - yarn publish --ignore-scripts archive.tgz - - - name: Publish Runtime - if: steps.check-tag.outputs.match == 'true' - env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - run: | - cd sdks/runtime/typescript - - npm config set '//registry.npmjs.org/:_authToken' "$NPM_TOKEN" - - yarn version --no-git-tag-version --new-version "${{ github.ref_name }}" - yarn pack --ignore-scripts -f archive.tgz - yarn publish --ignore-scripts archive.tgz diff --git a/.github/workflows/pkg-pr-new.yaml b/.github/workflows/pkg-pr-new.yaml index a4be82b707..a57fd6176e 100644 --- a/.github/workflows/pkg-pr-new.yaml +++ b/.github/workflows/pkg-pr-new.yaml @@ -1,24 +1,17 @@ -name: Continuous Release - on: pull_request: - paths: - - frontend/packages/cli/** - - sdks/actor/** jobs: publish: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 with: lfs: true - run: corepack enable - uses: actions/setup-node@v4 - - name: Install dependencies - run: yarn install - - - run: yarn build --filter='./{sdks,frontend/packages/cli}/**' - # TODO: Add --compact once we publish cli to npm - - run: rm -rf ./sdks/actor/client/node_modules; rm -rf ./sdks/actor/runtime/node_modules; rm -rf ./frontend/packages/cli/node_modules - - run: yarn dlx pkg-pr-new publish --yarn './sdks/actor/client' './frontend/packages/cli' \ No newline at end of file + with: + cache: "pnpm" + - run: pnpm install + - run: pnpm build -F @rivetkit/engine-runner-protocol -F @rivetkit/engine-tunnel-protocol -F @rivetkit/engine-runner + - run: pnpm dlx pkg-pr-new publish 'sdks/typescript/runner/' 'sdks/typescript/runner-protocol/' 'sdks/typescript/tunnel-protocol/' diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 89aa597d66..7744f93414 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -24,88 +24,77 @@ env: RUSTFLAGS: "--cfg tokio_unstable" jobs: - setup: - name: "Setup" - runs-on: ubuntu-24.04 - permissions: - # Allow pushing to GitHub - contents: write - # Allows JSR to authenticate with GitHub - id-token: write - steps: - - name: Checkout rivet - uses: actions/checkout@v4 - with: - lfs: 'true' - path: './rivet' - - - name: Checkout actor-core - uses: actions/checkout@v4 - with: - repository: 'rivet-gg/actor-core' - path: './actor-core' - - - uses: actions/setup-node@v4 - with: - node-version: 20 - - - run: corepack enable - - - name: Setup - env: - # Required to authenticate with Git - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - working-directory: './rivet' - run: | - # Configure Git - git config --global user.name "github-actions[bot]" - git config --global user.email "github-actions[bot]@users.noreply.github.com" - - # Install Deno - curl -fsSL https://deno.land/x/install/install.sh | sh - export PATH=$HOME/.deno/bin:$PATH - - # Authenticate with NPM - cat << EOF > ~/.yarnrc.yml - npmAuthToken: "${{ secrets.NPM_TOKEN }}" - EOF - - # TODO: CI yarn.lock differs from local for some reason & causes errors - # Install dependencies - # yarn install --immutable - yarn config set -H enableImmutableInstalls false - yarn install - - if [ "${{ inputs.latest }}" = "true" ]; then - ./scripts/release/main.ts --version "${{ github.event.inputs.version }}" --setupCi - else - ./scripts/release/main.ts --version "${{ github.event.inputs.version }}" --no-latest --setupCi - fi - + # setup: + # name: "Setup" + # runs-on: ubuntu-24.04 + # permissions: + # # Allow pushing to GitHub + # contents: write + # # Allows JSR to authenticate with GitHub + # id-token: write + # steps: + # - name: Checkout rivet + # uses: actions/checkout@v4 + # with: + # lfs: 'true' + # path: './rivet' + + # - uses: actions/setup-node@v4 + # with: + # node-version: 20 + + # - run: corepack enable + + # - name: Setup + # env: + # # Required to authenticate with Git + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # working-directory: './rivet' + # run: | + # # Configure Git + # git config --global user.name "github-actions[bot]" + # git config --global user.email "github-actions[bot]@users.noreply.github.com" + + # # Install Deno + # curl -fsSL https://deno.land/x/install/install.sh | sh + # export PATH=$HOME/.deno/bin:$PATH + + # # Authenticate with NPM + # cat << EOF > ~/.npmrc + # //registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }} + # EOF + + # pnpm install + + # if [ "${{ inputs.latest }}" = "true" ]; then + # ./scripts/release/main.ts --version "${{ github.event.inputs.version }}" --setupCi + # else + # ./scripts/release/main.ts --version "${{ github.event.inputs.version }}" --no-latest --setupCi + # fi binaries: name: "Build & Push Binaries" - needs: [setup] + # needs: [setup] strategy: matrix: include: - platform: linux - runner: [self-hosted, Linux, X64] + runner: ubuntu-latest target: x86_64-unknown-linux-musl binary_ext: "" arch: x86_64 - platform: windows - runner: [self-hosted, Linux, X64] + runner: ubuntu-latest target: x86_64-pc-windows-gnu binary_ext: ".exe" arch: x86_64 - platform: macos - runner: [self-hosted, Linux, X64] + runner: ubuntu-latest target: x86_64-apple-darwin binary_ext: "" arch: x86_64 - platform: macos - runner: [self-hosted, Linux, ARM64] + runner: ubuntu-latest target: aarch64-apple-darwin binary_ext: "" arch: aarch64 @@ -118,13 +107,13 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Build using toolchain Dockerfile + - name: Build using engine Dockerfile run: | # Use Docker BuildKit export DOCKER_BUILDKIT=1 # Build the binary using our Dockerfile - docker/toolchain/build.sh ${{ matrix.target }} + docker/engine/build.sh ${{ matrix.target }} # Make sure dist directory exists and binary is there ls -la dist/ @@ -148,28 +137,28 @@ jobs: ./aws/install --update COMMIT_SHA_SHORT="${GITHUB_SHA::7}" - BINARY_PATH="dist/rivet-${{ matrix.target }}${{ matrix.binary_ext }}" + BINARY_PATH="dist/rivet-engine-${{ matrix.target }}${{ matrix.binary_ext }}" # Must specify --checksum-algorithm for compatibility with R2 aws s3 cp \ "${BINARY_PATH}" \ - "s3://rivet/${COMMIT_SHA_SHORT}/rivet-${{ matrix.target }}${{ matrix.binary_ext }}" \ + "s3://rivet/${COMMIT_SHA_SHORT}/rivet-engine-${{ matrix.target }}${{ matrix.binary_ext }}" \ --region auto \ - --endpoint-url https://2a94c6a0ced8d35ea63cddc86c2681e7.r2.cloudflarestorage.com/rivet-releases \ + --endpoint-url https://2a94c6a0ced8d35ea63cddc86c2681e7.r2.cloudflarestorage.com/rivet-engine-releases \ --checksum-algorithm CRC32 docker: name: "Build & Push Docker Images" - needs: [setup] + # needs: [setup] strategy: matrix: include: # TODO(RVT-4479): Add back ARM builder once manifest generation fixed # - platform: linux/arm64 - # runner: [self-hosted, Linux, ARM64] + # runner: ubuntu-latest # arch_suffix: -arm64 - platform: linux/x86_64 - runner: [self-hosted, Linux, X64] + runner: ubuntu-latest # TODO: Replace with appropriate arch_suffix when needed # arch_suffix: -amd64 arch_suffix: '' @@ -198,100 +187,60 @@ jobs: docker_password: ${{ secrets.DOCKER_CI_ACCESS_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN}} - - name: Build & Push (rivetgg/server:full) - uses: docker/build-push-action@v4 - with: - context: . - push: true - tags: rivetgg/rivet-server:full-${{ steps.vars.outputs.sha_short }}${{ matrix.arch_suffix }} - file: docker/universal/Dockerfile - target: server-full - platforms: ${{ matrix.platform }} - secrets: | - fontawesome_package_token=${{ secrets.FONTAWESOME_PACKAGE_TOKEN }} - secret-files: | - netrc=${{ runner.temp }}/netrc - - - name: Build & Push (rivetgg/server:slim) - uses: docker/build-push-action@v4 - with: - context: . - push: true - tags: rivetgg/rivet-server:slim-${{ steps.vars.outputs.sha_short }}${{ matrix.arch_suffix }} - file: docker/universal/Dockerfile - target: server-slim - platforms: ${{ matrix.platform }} - secrets: | - fontawesome_package_token=${{ secrets.FONTAWESOME_PACKAGE_TOKEN }} - secret-files: | - netrc=${{ runner.temp }}/netrc - - - name: Build & Push (rivetgg/server:slim) - uses: docker/build-push-action@v4 - with: - context: . - push: true - tags: rivetgg/rivet-server:slim-${{ steps.vars.outputs.sha_short }}${{ matrix.arch_suffix }} - file: docker/universal/Dockerfile - target: server-slim - platforms: ${{ matrix.platform }} - secret-files: | - netrc=${{ runner.temp }}/netrc - - - name: Build & Push (rivetgg/client:full) + - name: Build & Push (rivetgg/engine:full) uses: docker/build-push-action@v4 with: context: . push: true - tags: rivetgg/rivet-client:full-${{ steps.vars.outputs.sha_short }}${{ matrix.arch_suffix }} + tags: rivetgg/rivet-engine:full-${{ steps.vars.outputs.sha_short }}${{ matrix.arch_suffix }} file: docker/universal/Dockerfile - target: client-full + target: engine-full platforms: ${{ matrix.platform }} - secrets: | - fontawesome_package_token=${{ secrets.FONTAWESOME_PACKAGE_TOKEN }} - secret-files: | - netrc=${{ runner.temp }}/netrc + # secrets: | + # fontawesome_package_token=${{ secrets.FONTAWESOME_PACKAGE_TOKEN }} + # secret-files: | + # netrc=${{ runner.temp }}/netrc - - name: Build & Push (rivetgg/rivet:monolith) + - name: Build & Push (rivetgg/engine:slim) uses: docker/build-push-action@v4 with: context: . push: true - tags: rivetgg/rivet:monolith-${{ steps.vars.outputs.sha_short }}${{ matrix.arch_suffix }} + tags: rivetgg/rivet-engine:slim-${{ steps.vars.outputs.sha_short }}${{ matrix.arch_suffix }} file: docker/universal/Dockerfile - target: monolith + target: engine-slim platforms: ${{ matrix.platform }} - secrets: | - fontawesome_package_token=${{ secrets.FONTAWESOME_PACKAGE_TOKEN }} - secret-files: | - netrc=${{ runner.temp }}/netrc - - complete: - name: "Complete" - needs: [binaries, docker] - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@v4 - with: - lfs: 'true' - - - uses: ./.github/actions/docker-setup - with: - docker_username: ${{ secrets.DOCKER_CI_USERNAME }} - docker_password: ${{ secrets.DOCKER_CI_ACCESS_TOKEN }} - github_token: ${{ secrets.GITHUB_TOKEN}} - - - name: Complete - env: - R2_RELEASES_ACCESS_KEY_ID: ${{ secrets.R2_RELEASES_ACCESS_KEY_ID }} - R2_RELEASES_SECRET_ACCESS_KEY: ${{ secrets.R2_RELEASES_SECRET_ACCESS_KEY }} - run: | - # Install Deno - curl -fsSL https://deno.land/x/install/install.sh | sh - export PATH=$HOME/.deno/bin:$PATH - - if [ "${{ inputs.latest }}" = "true" ]; then - ./scripts/release/main.ts --version "${{ github.event.inputs.version }}" --completeCi - else - ./scripts/release/main.ts --version "${{ github.event.inputs.version }}" --no-latest --completeCi - fi + # secrets: | + # fontawesome_package_token=${{ secrets.FONTAWESOME_PACKAGE_TOKEN }} + # secret-files: | + # netrc=${{ runner.temp }}/netrc + + # complete: + # name: "Complete" + # needs: [docker] + # runs-on: ubuntu-24.04 + # steps: + # - uses: actions/checkout@v4 + # with: + # lfs: 'true' + + # - uses: ./.github/actions/docker-setup + # with: + # docker_username: ${{ secrets.DOCKER_CI_USERNAME }} + # docker_password: ${{ secrets.DOCKER_CI_ACCESS_TOKEN }} + # github_token: ${{ secrets.GITHUB_TOKEN}} + + # - name: Complete + # env: + # R2_RELEASES_ACCESS_KEY_ID: ${{ secrets.R2_RELEASES_ACCESS_KEY_ID }} + # R2_RELEASES_SECRET_ACCESS_KEY: ${{ secrets.R2_RELEASES_SECRET_ACCESS_KEY }} + # run: | + # # Install Deno + # curl -fsSL https://deno.land/x/install/install.sh | sh + # export PATH=$HOME/.deno/bin:$PATH + + # if [ "${{ inputs.latest }}" = "true" ]; then + # ./scripts/release/main.ts --version "${{ github.event.inputs.version }}" --completeCi + # else + # ./scripts/release/main.ts --version "${{ github.event.inputs.version }}" --no-latest --completeCi + # fi diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml deleted file mode 100644 index 0477a4d867..0000000000 --- a/.github/workflows/rust.yaml +++ /dev/null @@ -1,63 +0,0 @@ -name: rust - -on: - pull_request: - paths-ignore: - - 'frontend/**' - push: - branches: - - main - -concurrency: - group: rust-${{ github.ref }} - cancel-in-progress: true - -permissions: {} - -defaults: - run: - # Enable fail-fast behavior - shell: bash -e {0} - -env: - # Disable incremental compilation for faster from-scratch builds - CARGO_INCREMENTAL: 0 - RUSTFLAGS: "--cfg tokio_unstable" - -jobs: - cargo-fmt: - runs-on: ubuntu-20.04 - container: - image: rust:1.82.0 - steps: - - uses: actions/checkout@v4 - - run: rustup component add rustfmt - - run: cargo fmt --check - - cargo-check-main: - runs-on: [self-hosted, Linux, X64] - container: - image: rust:1.82.0 - steps: - - uses: actions/checkout@v4 - - name: Install dependencies - # TODO(RVT-4168): Compile libfdb from scratch for ARM - # The FDB version should match `cluster::workflows::server::install::install_scripts::components::fdb::FDB_VERSION` - run: | - apt-get update - apt-get install -y protobuf-compiler libpq-dev curl libclang-dev - curl -Lf -o /lib/libfdb_c.so "https://github.com/apple/foundationdb/releases/download/7.1.60/libfdb_c.x86_64.so" - - run: RUSTFLAGS="--cfg tokio_unstable" cargo check --release - env: - # Expose token for pulling GH artifacts - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - cargo-deny: - runs-on: ubuntu-20.04 - container: - image: rust:1.82.0 - steps: - - uses: actions/checkout@v4 - - name: cargo deny - uses: EmbarkStudios/cargo-deny-action@v1 - diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 0000000000..1671a3fc41 --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,101 @@ +name: Rust CI + +on: + pull_request: + paths-ignore: + - 'frontend/**' + push: + branches: + - main + +concurrency: + group: rust-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +defaults: + run: + # Enable fail-fast behavior + shell: bash -e {0} + +env: + # Disable incremental compilation for faster from-scratch builds + CARGO_INCREMENTAL: 0 + RUSTFLAGS: "--cfg tokio_unstable" + CARGO_TERM_COLOR: always + +jobs: + fmt: + name: Rustfmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: stable + components: rustfmt + + - name: Check formatting + run: cargo fmt --all -- --check + + # clippy: + # name: Clippy + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + + # - uses: actions-rust-lang/setup-rust-toolchain@v1 + # with: + # toolchain: stable + # components: clippy + + # - uses: Swatinem/rust-cache@v2 + + # - name: Run clippy + # run: cargo clippy --all-targets --all-features -- -W warnings + + check: + name: Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: stable + + - uses: Swatinem/rust-cache@v2 + + - name: Check + run: cargo check --all-targets --all-features + env: + # Deny warnings + RUSTFLAGS: --cfg tokio_unstable -D warnings + + test: + name: Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: stable + + - uses: Swatinem/rust-cache@v2 + + - name: Run tests + run: cargo test --verbose + + deny: + name: Deny + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: cargo deny + uses: EmbarkStudios/cargo-deny-action@v1 + with: + rust-version: "1.88.0" diff --git a/.gitignore b/.gitignore index fa911fff32..809682214c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,44 +1,52 @@ -# Keep all .gitignore files in this file so we can easily keep it in sync with .dockerignore -# -# Make sure to update .dockerignore appropriately - -**/.DS_Store -**/*.tmp - -# Env -.env*.local - # Rust +lib/**/Cargo.lock +!lib/bolt/Cargo.lock + +# Allows symlinking target instead of being a directory **/target +**/target/ +**/*.rustfmt -# JavaScript -**/*.log* -**/.cache/ -**/.next/ +# Turborepo **/.turbo -**/.yarn -**/dist/ -**/node_modules/ -**/vendor/ -**/target -# Site -site/out/ -site/public/rss/ -!site/public/rss/.gitkeep -# Generated Markdown -site/public/docs/ +# Node.js and pnpm +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* -site/src/generated/ -!site/src/generated/errorPages.json -!site/src/generated/apiPages.json -!site/src/generated/meta.json +# pnpm workspace +.pnpm-store/ + +# TypeScript +*.tsbuildinfo +dist/ + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# OS +.DS_Store +Thumbs.db -# Icons -frontend/packages/icons/src/* +secrets/**/* -# HACK: Unsure why these artifacts are generated when running fern generate -frontend/apps/hub/vite.config.ts.* +tf/.terraform/**/* +tf/.terraform.lock.hcl -.aider* +# Frontend +frontend/.env.* +frontend/dist/ +frontend/node_modules/ +# Site +site/.next/ +site/src/generated/ +site/public/docs/ +site/public/llms-full.txt +site/public/llms.txt diff --git a/.vim/coc-settings.json b/.vim/coc-settings.json deleted file mode 100644 index 15bf69b26a..0000000000 --- a/.vim/coc-settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "protoc": { - "options": ["-I=proto/proto"] - } -} diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index c203740924..0000000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "recommendations": [ - "unifiedjs.vscode-mdx" - ] -} \ No newline at end of file diff --git a/.vscode/frontend.code-workspace b/.vscode/frontend.code-workspace deleted file mode 100644 index 0943a74737..0000000000 --- a/.vscode/frontend.code-workspace +++ /dev/null @@ -1,31 +0,0 @@ -{ - "folders": [ - { - "path": "../frontend/apps/hub" - }, - { - "path": "../frontend/packages/components" - }, - { - "path": "../frontend/packages/icons" - }, - { - "path": "../examples/react" - }, - { - "path": "../site" - }, - { - "path": "../sdks/actor/client" - }, - { - "path": "../sdks/actor/runtime" - }, - ], - "settings": {}, - "extensions": { - "recommendations": [ - "vercel.turbo-vsc" - ] - } -} \ No newline at end of file diff --git a/.vscode/rivet.code-workspace b/.vscode/rivet.code-workspace deleted file mode 100644 index 36a6dc350a..0000000000 --- a/.vscode/rivet.code-workspace +++ /dev/null @@ -1,3 +0,0 @@ -{ - "folders": [] -} diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index dbf93c0c55..0000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "protoc": { - "options": ["-I=proto/proto"] - }, - "[rust]": { - "editor.formatOnSave": true, - "editor.tabSize": 4 - }, - "[proto3]": { - "editor.insertSpaces": true, - "editor.tabSize": 4 - }, - "[typescript]": { - "editor.formatOnSave": true - }, - "files.exclude": { - "**/.git": true, - "**/.cargo": true, - "**/.vim": true, - "**/.svn": true, - "**/.hg": true, - "**/CVS": true, - "**/.DS_Store": true, - "**/gen": true - }, - "files.watcherExclude": { - "**/target/**": true - }, - "python.formatting.provider": "black", - "grammarly.selectors": [ - { - "language": "markdown", - "scheme": "file" - } - ], - // Override CARGO_TARGET_DIR in order to prevent locking or cobbling the main target. - // - // Cargo often uses a diferent Rust version than RA because of Nix. - "rust-analyzer.cargo.extraEnv": { - "RUSTFLAGS": "--cfg tokio_unstable", - "CARGO_TARGET_DIR": "${workspaceFolder}/target/analyzer" - }, - "rust-analyzer.server.extraEnv": { - "CARGO_TARGET_DIR": "${workspaceFolder}/target/analyzer" - }, - "rust-analyzer.cargo.targetDir": "${workspaceFolder}/target/analyzer", -} diff --git a/.yarnrc.yml b/.yarnrc.yml deleted file mode 100644 index 3e058a26cc..0000000000 --- a/.yarnrc.yml +++ /dev/null @@ -1,5 +0,0 @@ -nodeLinker: node-modules - -npmScopes: - jsr: - npmRegistryServer: "https://npm.jsr.io" \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index 63eb799f03..ad057c6673 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,4 +1,184 @@ -- Do not use cat, hexdump, perl, or sed. Always edit files directly. -- If attempting to use Cargo, use `nix-shell --command 'cargo ...'` -- Public API specs live in sdks/api/fern/ -- When modifying sdks/api/fern/, run ./scripts/fern/gen.sh to regenerate the related libraries \ No newline at end of file +# CLAUDE.md + +## Commands + +### Build Commands +```bash +# Build all packages in the workspace +cargo build + +# Build a specific package +cargo build -p package-name + +# Build with release optimizations +cargo build --release +``` + +### Test Commands +```bash +# Run all tests in the workspace +cargo test + +# Run tests for a specific package +cargo test -p package-name + +# Run a specific test +cargo test test_name + +# Run tests with output displayed +cargo test -- --nocapture +``` + +### Development Commands +```bash +# Format code (enforced by pre-commit hooks) +# cargo fmt +# DO NOT RUN CARGO FMT AUTOMATICALLY (note for humans: we need to run cargo fmt when everything is merged together and make sure lefthook is working) + +# Run linter and fix issues +./scripts/cargo/fix.sh + +# Check for linting issues +cargo clippy -- -W warnings + +# When adding a new package to the workspace +deno run -A scripts/cargo/update_workspace.ts +``` + +### Docker Development Environment +```bash +# Start the development environment with all services +cd docker/dev +docker-compose up -d +``` + +### Git Commands +```bash +# When committing changes, use Graphite CLI with conventional commits +gt c -m "chore(my-pkg): foo bar" +``` + +## Graphite CLI Commands +```bash +# Modify a Graphite PR +gt m +``` + +## Dependency Management +- Use pnpm for all npm-related commands. We're using a pnpm workspace. + +## Documentation + +- If you need to look at the documentation for a package, visit `https://docs.rs/{package-name}`. For example, serde docs live at https://docs.rs/serde/ + +## Architecture + +### Monorepo Structure +This is a Rust workspace-based monorepo for Rivet. Key packages and components: + +- **Core Engine** (`packages/core/engine/`) - Main orchestration service that coordinates all operations +- **Workflow Engine** (`packages/common/gasoline/`) - Handles complex multi-step operations with reliability and observability +- **Pegboard** (`packages/core/pegboard/`) - Actor/server lifecycle management system +- **Common Packages** (`/packages/common/`) - Foundation utilities, database connections, caching, metrics, logging, health checks, workflow engine core +- **Core Packages** (`/packages/core/`) - Main engine executable, Pegboard actor orchestration, workflow workers +- **Service Infrastructure** - Distributed services communicate via NATS messaging with service discovery + +### Important Patterns + +**Error Handling** +- Custom error system at `packages/common/error/` +- Uses derive macros with struct-based error definitions + +To use custom errors: + +```rust +use rivet_error::*; +use serde::{Serialize, Deserialize}; + +// Simple error without metadata +#[derive(RivetError)] +#[error("auth", "invalid_token", "The provided authentication token is invalid")] +struct AuthInvalidToken; + +// Error with metadata +#[derive(RivetError, Serialize, Deserialize)] +#[error( + "api", + "rate_limited", + "Rate limit exceeded", + "Rate limit exceeded. Limit: {limit}, resets at: {reset_at}" +)] +struct ApiRateLimited { + limit: u32, + reset_at: i64, +} + +// Use errors in code +let error = AuthInvalidToken.build(); +let error_with_meta = ApiRateLimited { limit: 100, reset_at: 1234567890 }.build(); +``` + +Key points: +- Use `#[derive(RivetError)]` on struct definitions +- Use `#[error(group, code, description)]` or `#[error(group, code, description, formatted_message)]` attribute +- Group errors by module/domain (e.g., "auth", "actor", "namespace") +- Add `Serialize, Deserialize` derives for errors with metadata fields +- Always return anyhow errors from failable functions + - For example: `fn foo() -> Result { /* ... */ }` +- Import anyhow using `use anyhow::*` instead of importing individual types + +**Dependency Management** +- When adding a dependency, check for a workspace dependency in Cargo.toml +- If available, use the workspace dependency (e.g., `anyhow.workspace = true`) +- If you need to add a dependency and can't find it in the Cargo.toml of the workspace, add it to the workspace dependencies in Cargo.toml (`[workspace.dependencies]`) and then add it to the package you need with `{dependency}.workspace = true` + +**Database Usage** +- UniversalDB for distributed state storage +- ClickHouse for analytics and time-series data +- Connection pooling through `packages/common/pools/` + +### Code Style +- Hard tabs for Rust formatting (see `rustfmt.toml`) +- Follow existing patterns in neighboring files +- Always check existing imports and dependencies before adding new ones +- **Always add imports at the top of the file inside of inline within the function.** + +## Naming Conventions + +Data structures often include: + +- `id` (uuid) +- `name` (machine-readable name, must be valid DNS subdomain, convention is using kebab case) +- `description` (human-readable, if applicable) + +## Implementation Details + +### Data Storage Conventions +- Use UUID (v4) for generating unique identifiers +- Store dates as i64 epoch timestamps in milliseconds for precise time tracking + +### Timestamp Naming Conventions +- When storing timestamps, name them *_at with past tense verb. For example, created_at, destroyed_at. + +## Logging Patterns + +### Structured Logging +- Use tracing for logging. Do not format parameters into the main message, instead use tracing's structured logging. + - For example, instead of `tracing::info!("foo {x}")`, do `tracing::info!(?x, "foo")` +- Log messages should be lowercase unless mentioning specific code symbols. For example, `tracing::info!("inserted UserRow")` instead of `tracing::info!("Inserted UserRow")` + +## Configuration Management + +### Docker Development Configuration +- Do not make changes to docker/dev* configs. Instead, edit the template in docker/template/ and rerun (cd docker/template && pnpm start). This will regenerate the docker compose config for you. + +## Development Warnings + +- Do not run ./scripts/cargo/fix.sh. Do not format the code yourself. + +## Testing Guidelines +- When running tests, always pipe the test to a file in /tmp/ then grep it in a second step. You can grep test logs multiple times to search for different log lines. + +## Optimizations + +- Never build a new reqwest client from scratch. Use `rivet_pools::reqwest::client().await?` to access an existing reqwest client instance. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index d34d9c7ae6..0000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,69 +0,0 @@ -# Contributing - -The Rivet repository is a monorepo. Each component has its own README.md -including information on how to develop it. - -## Development Quickstart - -- [Rivet Cluster](docker/dev-full/README.md) -- [CLI](packages/toolchain/cli/README.md) -- [Actor SDK](sdks/actor/README.md) -- [Site & Docs](site/README.md) -- [Hub](frontend/apps/hub) -- [Examples](examples/README.md) - -## Justfile - -It's recommended to use [just](https://github.com/casey/just) to run development commands, though not required. - -## Nix Environment - -It's recommended to install the [Nix package manager](https://nixos.org/download/) in order to build a consistent environment. - -Once installed, run `nix-shell` to build your development environment. - -## Conventions - -- [Naming conventions](./docs-internal/development/NAMING_CONVENTIONS.md). -- [Internal <-> External Aliases](./docs-internal/development/INTERNAL_EXTERNAL_ALIASES.md). - -## Making Changes - -### For Open Source Contributors - -1. **Fork and Clone**: Fork the repository and clone it locally. -2. **Branch**: Create a feature or bugfix branch. -3. **Pull Request**: - - Provide a clear title and description. The title must follow - [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/). These are used for generating our - changelogs with [Release Please](https://github.com/googleapis/release-please). - - Link the related GitHub issue (if applicable). - - Validate that required checks pass. We ensure that Rivet's required checks run within < 5 minutes. - -### For Rivet Employees - -1. **Branching and Commits**: - - Use [Graphite](https://graphite.dev/) for creating and managing branches. - - Follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification when - creating branches. -2. **Pull Request**: - - Push your branch to the repo and request a review through Graphite. - - Link related Linear issues in your PR body using the "magic words" `Fixes XXX-123`. - [More information.](https://linear.app/docs/github#link-using-pull-requests) - - Manually mark your issue as _Ready to Merge_ when ready. - - Validate that required checks pass. We ensure that required checks run within reasonable time. -3. **Merging**: - - Once approved, it's up to you to merge your commit. If deploying the frontend, make sure to monitor the - changes from Sentry before going offline. - - Manually mark your issue as _Complete_ once finished. - -### Release - -```sh -# Release latest -just release-latest VERSION - -# Release no latest (including rc) -just release-nolatest VERSION -``` - diff --git a/Cargo.lock b/Cargo.lock index 799e73dc4c..3836093ca0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,32 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "Inflector" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" -dependencies = [ - "lazy_static", - "regex", -] - -[[package]] -name = "acme-lib" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bcfe879d8669cfe09f2dd1bef4dc8cb232ca7b9ce46f4621cda9e7cc729cf73" -dependencies = [ - "base64 0.21.7", - "lazy_static", - "log", - "openssl", - "serde", - "serde_json", - "time 0.1.45", - "ureq", -] - [[package]] name = "addr2line" version = "0.24.2" @@ -37,98 +11,22 @@ dependencies = [ "gimli", ] -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - -[[package]] -name = "aead" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" -dependencies = [ - "crypto-common", - "generic-array", -] - -[[package]] -name = "aead-gcm-stream" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4947a169074c7e038fa43051d1c4e073f4488b0e4b0a30658f1e1a1b06449ce8" -dependencies = [ - "aead", - "aes", - "cipher", - "ctr", - "ghash", - "subtle", -] - -[[package]] -name = "aes" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "aes-gcm" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" -dependencies = [ - "aead", - "aes", - "cipher", - "ctr", - "ghash", - "subtle", -] - -[[package]] -name = "aes-kw" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69fa2b352dcefb5f7f3a5fb840e02665d311d878955380515e4fd50095dd3d8c" -dependencies = [ - "aes", -] - -[[package]] -name = "ahash" -version = "0.7.8" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" -dependencies = [ - "getrandom 0.2.15", - "once_cell", - "version_check", -] +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "ahash" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", - "getrandom 0.2.15", "once_cell", "version_check", - "zerocopy 0.7.35", + "zerocopy", ] [[package]] @@ -140,21 +38,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "alloc-no-stdlib" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" - -[[package]] -name = "alloc-stdlib" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" -dependencies = [ - "alloc-no-stdlib", -] - [[package]] name = "allocator-api2" version = "0.2.21" @@ -191,15 +74,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "220044e6a1bb31ddee4e3db724d29767f352de47445a6cd75e1a173142136c83" dependencies = [ - "nom 7.1.3", - "vte 0.10.1", + "nom", + "vte", ] [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" dependencies = [ "anstyle", "anstyle-parse", @@ -212,16898 +95,5990 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" dependencies = [ "anstyle", + "once_cell_polyfill", "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.95" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] -name = "api-auth" -version = "25.5.2" +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" dependencies = [ - "api-helper", - "async-trait", - "captcha-verify", - "chirp-client", - "chirp-workflow", - "chrono", - "debug-email-res", - "email-verification-complete", - "email-verification-create", - "faker-user", - "headers", - "http 0.2.12", - "hyper 0.14.31", - "lazy_static", - "prost 0.10.4", - "rivet-api", - "rivet-auth", - "rivet-auth-server", - "rivet-cache", - "rivet-claims", - "rivet-config", - "rivet-connection", - "rivet-convert", - "rivet-env", - "rivet-health-checks", - "rivet-operation", - "rivet-pools", - "serde", - "serde_json", - "thiserror 1.0.69", - "token-create", - "token-revoke", - "tokio", - "tracing", - "tracing-subscriber", - "url", - "user", - "user-get", - "user-identity-create", - "user-identity-get", - "user-resolve-email", - "user-token-create", - "uuid", + "num-traits", ] [[package]] -name = "api-cf-verification" -version = "25.5.2" +name = "arraydeque" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "assert-json-diff" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12" dependencies = [ - "api-helper", - "async-trait", - "bytes", - "cf-custom-hostname-get", - "chirp-client", - "chrono", - "faker-game", - "http 0.2.12", - "hyper 0.14.31", - "lazy_static", - "prost 0.10.4", - "rivet-cache", - "rivet-cf-verification", - "rivet-cf-verification-server", - "rivet-claims", - "rivet-config", - "rivet-connection", - "rivet-env", - "rivet-health-checks", - "rivet-operation", - "rivet-pools", "serde", "serde_json", - "thiserror 1.0.69", - "tokio", - "tracing", - "tracing-subscriber", - "url", - "uuid", ] [[package]] -name = "api-cloud" -version = "25.5.2" +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" dependencies = [ - "api-helper", - "async-trait", - "base64 0.13.1", - "build-create", - "build-get", - "build-list-for-game", - "bytes", - "cdn-namespace-auth-user-remove", - "cdn-namespace-auth-user-update", - "cdn-namespace-domain-create", - "cdn-namespace-domain-remove", - "cdn-ns-auth-type-set", - "cdn-ns-enable-domain-public-auth-set", - "cdn-site-create", - "cdn-site-get", - "cdn-site-list-for-game", - "cf-custom-hostname-list-for-namespace-id", - "chirp-client", - "chrono", - "cloud-device-link-create", - "cloud-game-config-create", - "cloud-game-config-get", - "cloud-game-token-create", - "cloud-namespace-create", - "cloud-namespace-get", - "cloud-namespace-token-development-create", - "cloud-namespace-token-public-create", - "cloud-version-get", - "cloud-version-publish", - "cluster", - "custom-user-avatar-list-for-game", - "custom-user-avatar-upload-complete", - "faker-region", - "faker-team", - "futures-util", - "game-banner-upload-complete", - "game-create", - "game-get", - "game-list-for-team", - "game-logo-upload-complete", - "game-namespace-create", - "game-namespace-get", - "game-namespace-list", - "game-namespace-validate", - "game-namespace-version-history-list", - "game-namespace-version-set", - "game-resolve-namespace-id", - "game-token-development-validate", - "game-validate", - "game-version-get", - "game-version-list", - "game-version-validate", - "http 0.2.12", - "hyper 0.14.31", - "job-log-read", - "job-run", - "lazy_static", - "mm-config-lobby-group-get", - "mm-config-lobby-group-resolve-version", - "mm-config-namespace-config-set", - "mm-config-namespace-config-validate", - "mm-config-version-get", - "mm-lobby-get", - "mm-lobby-history", - "mm-lobby-list-for-namespace", - "mm-lobby-player-count", - "mm-lobby-runtime-aggregate", - "mm-player-count-for-namespace", - "prost 0.10.4", - "rand 0.8.5", - "region-get", - "region-list-for-game", - "reqwest 0.11.27", - "rivet-api", - "rivet-cache", - "rivet-claims", - "rivet-config", - "rivet-connection", - "rivet-convert", - "rivet-env", - "rivet-health-checks", - "rivet-operation", - "rivet-pools", - "rivet-util-job", - "rivet-util-mm", - "rivet-util-team", - "s3-util", - "serde", - "serde_json", - "team-get", - "team-member-count", - "team-validate", - "thiserror 1.0.69", - "tier", - "token-create", - "token-revoke", - "tokio", - "tracing", - "tracing-subscriber", - "upload-complete", - "upload-file-list", - "upload-get", - "upload-prepare", - "url", - "user-get", - "user-identity-create", - "user-identity-get", - "user-team-list", - "uuid", + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", ] [[package]] -name = "api-core-actor" -version = "25.5.2" +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "api-helper", - "base64 0.13.1", - "build", - "build-create", - "build-get", - "build-list-for-env", - "cdn-namespace-domain-create", - "chirp-client", - "chrono", - "clickhouse-user-query", - "cloud-namespace-token-development-create", - "cloud-namespace-token-public-create", - "cluster", - "core-guard", - "faker-build", - "faker-game", - "faker-game-namespace", - "faker-game-version", - "faker-region", - "game-get", - "game-namespace-get", - "game-namespace-resolve-name-id", - "game-resolve-name-id", - "game-version-get", - "http 0.2.12", - "hyper 0.14.31", - "lazy_static", - "pegboard", - "region-get", - "region-recommend", - "reqwest 0.11.27", - "rivet-api", - "rivet-cache", - "rivet-claims", - "rivet-config", - "rivet-connection", - "rivet-convert", - "rivet-env", - "rivet-health-checks", - "rivet-operation", - "rivet-pools", - "rivet-util-team", - "route", - "s3-util", - "serde", - "serde_json", - "team-get", - "token-create", - "token-revoke", - "tokio", - "tracing", - "tracing-futures", - "tracing-subscriber", - "upload-complete", - "upload-get", - "upload-prepare", - "url", - "user-get", - "user-identity-get", - "user-team-list", - "uuid", + "event-listener", + "event-listener-strategy", + "pin-project-lite", ] [[package]] -name = "api-core-intercom" -version = "25.5.2" +name = "async-nats" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc1f1a75fd07f0f517322d103211f12d757658e91676def9a2e688774656c60" dependencies = [ - "api-helper", - "async-trait", - "chirp-client", - "chirp-workflow", - "chrono", - "cluster", + "base64 0.21.7", + "bytes", + "futures", "http 0.2.12", - "hyper 0.14.31", - "lazy_static", - "prost 0.10.4", - "rivet-api", - "rivet-cache", - "rivet-claims", - "rivet-config", - "rivet-convert", - "rivet-env", - "rivet-health-checks", - "rivet-operation", - "rivet-pools", + "memchr", + "nkeys", + "nuid", + "once_cell", + "rand 0.8.5", + "regex", + "ring", + "rustls 0.21.12", + "rustls-native-certs", + "rustls-pemfile 1.0.4", + "rustls-webpki 0.101.7", "serde", "serde_json", + "serde_nanos", + "serde_repr", "thiserror 1.0.69", + "time", "tokio", + "tokio-retry", + "tokio-rustls 0.24.1", "tracing", - "tracing-subscriber", "url", - "uuid", ] [[package]] -name = "api-core-monolith-edge" -version = "25.5.2" +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ - "api-core-intercom", - "api-core-traefik-provider", - "api-helper", - "api-provision", - "async-trait", - "chirp-client", - "http 0.2.12", - "hyper 0.14.31", - "rivet-config", - "rivet-env", - "rivet-operation", - "tokio", - "tracing", - "tracing-subscriber", - "url", + "async-stream-impl", + "futures-core", + "pin-project-lite", ] [[package]] -name = "api-core-monolith-public" -version = "25.5.2" +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ - "api-auth", - "api-cf-verification", - "api-cloud", - "api-core-actor", - "api-games", - "api-group", - "api-helper", - "api-identity", - "api-job", - "api-matchmaker", - "api-portal", - "api-status", - "api-ui", - "async-trait", - "chirp-client", - "http 0.2.12", - "hyper 0.14.31", - "rivet-config", - "rivet-env", - "rivet-operation", - "tokio", - "tracing", - "tracing-subscriber", - "url", + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "api-core-traefik-provider" -version = "25.5.2" -dependencies = [ - "api-helper", - "async-trait", - "async_once", - "base64 0.13.1", - "cdn-namespace-auth-user-update", - "cdn-namespace-domain-create", - "chirp-client", - "chrono", - "cluster", - "faker-cdn-site", - "faker-game", - "faker-game-namespace", - "faker-game-version", - "faker-job-run", - "faker-region", - "game-get", - "http 0.2.12", - "hyper 0.14.31", - "lazy_static", - "pegboard", - "prost 0.10.4", - "reqwest 0.11.27", - "rivet-cache", - "rivet-claims", - "rivet-config", - "rivet-connection", - "rivet-convert", - "rivet-env", - "rivet-health-checks", - "rivet-operation", - "rivet-pools", - "rivet-route", - "rivet-util-cdn", - "rivet-util-job", - "s3-util", - "serde", - "serde_json", - "sqlx", - "thiserror 1.0.69", - "tokio", - "tracing", - "tracing-subscriber", - "url", - "uuid", -] - -[[package]] -name = "api-edge-actor" -version = "25.5.2" -dependencies = [ - "api-helper", - "base64 0.13.1", - "build", - "build-create", - "build-get", - "build-list-for-env", - "cdn-namespace-domain-create", - "chirp-client", - "chirp-workflow", - "chrono", - "cloud-namespace-token-development-create", - "cloud-namespace-token-public-create", - "cluster", - "faker-build", - "faker-game", - "faker-game-namespace", - "faker-game-version", - "faker-region", - "game-get", - "game-namespace-get", - "game-namespace-resolve-name-id", - "game-resolve-name-id", - "game-version-get", - "http 0.2.12", - "hyper 0.14.31", - "lazy_static", - "pegboard", - "region-get", - "region-recommend", - "reqwest 0.11.27", - "rivet-api", - "rivet-cache", - "rivet-claims", - "rivet-config", - "rivet-connection", - "rivet-convert", - "rivet-env", - "rivet-health-checks", - "rivet-operation", - "rivet-pools", - "rivet-util-team", - "s3-util", - "serde", - "serde_json", - "team-get", - "token-create", - "token-revoke", - "tokio", - "tracing", - "tracing-futures", - "tracing-subscriber", - "upload-complete", - "upload-get", - "url", - "user-get", - "user-identity-get", - "user-team-list", - "uuid", -] - -[[package]] -name = "api-edge-intercom" -version = "25.5.2" -dependencies = [ - "api-helper", - "async-trait", - "build", - "chirp-client", - "chirp-workflow", - "chrono", - "cluster", - "fdb-util", - "foundationdb", - "http 0.2.12", - "hyper 0.14.31", - "lazy_static", - "pegboard", - "prost 0.10.4", - "rivet-api", - "rivet-cache", - "rivet-claims", - "rivet-config", - "rivet-convert", - "rivet-env", - "rivet-health-checks", - "rivet-operation", - "rivet-pools", - "s3-util", - "serde", - "serde_json", - "thiserror 1.0.69", - "tokio", - "tracing", - "tracing-subscriber", - "upload-get", - "url", - "uuid", -] - -[[package]] -name = "api-edge-monolith-edge" -version = "25.5.2" -dependencies = [ - "api-edge-traefik-provider", - "api-helper", - "async-trait", - "chirp-client", - "http 0.2.12", - "hyper 0.14.31", - "rivet-config", - "rivet-env", - "rivet-operation", - "tokio", - "tracing", - "tracing-subscriber", - "url", -] - -[[package]] -name = "api-edge-monolith-public" -version = "25.5.2" -dependencies = [ - "api-edge-actor", - "api-edge-intercom", - "api-helper", - "async-trait", - "chirp-client", - "http 0.2.12", - "hyper 0.14.31", - "rivet-config", - "rivet-env", - "rivet-operation", - "tokio", - "tracing", - "tracing-subscriber", - "url", -] - -[[package]] -name = "api-edge-traefik-provider" -version = "25.5.2" -dependencies = [ - "api-core-traefik-provider", - "api-helper", - "async-trait", - "async_once", - "base64 0.13.1", - "cdn-namespace-auth-user-update", - "cdn-namespace-domain-create", - "chirp-client", - "chirp-workflow", - "chrono", - "faker-cdn-site", - "faker-game", - "faker-game-namespace", - "faker-game-version", - "faker-job-run", - "faker-region", - "fdb-util", - "foundationdb", - "game-get", - "http 0.2.12", - "hyper 0.14.31", - "lazy_static", - "pegboard", - "prost 0.10.4", - "reqwest 0.11.27", - "rivet-cache", - "rivet-claims", - "rivet-config", - "rivet-connection", - "rivet-convert", - "rivet-env", - "rivet-health-checks", - "rivet-operation", - "rivet-pools", - "rivet-route", - "rivet-util-cdn", - "rivet-util-job", - "s3-util", - "serde", - "serde_json", - "sqlx", - "thiserror 1.0.69", - "tokio", - "tracing", - "tracing-subscriber", - "url", - "uuid", -] - -[[package]] -name = "api-games" -version = "25.5.2" -dependencies = [ - "api-helper", - "base64 0.13.1", - "build", - "build-create", - "build-get", - "build-list-for-env", - "cdn-namespace-domain-create", - "chirp-client", - "chrono", - "cloud-namespace-token-development-create", - "cloud-namespace-token-public-create", - "cluster", - "faker-build", - "faker-game", - "faker-game-namespace", - "faker-game-version", - "faker-region", - "game-get", - "game-namespace-get", - "game-version-get", - "http 0.2.12", - "hyper 0.14.31", - "lazy_static", - "pegboard", - "region-get", - "reqwest 0.11.27", - "rivet-api", - "rivet-cache", - "rivet-claims", - "rivet-config", - "rivet-connection", - "rivet-convert", - "rivet-env", - "rivet-health-checks", - "rivet-operation", - "rivet-pools", - "rivet-util-team", - "s3-util", - "serde", - "serde_json", - "team-get", - "token-create", - "token-revoke", - "tokio", - "tracing", - "tracing-futures", - "tracing-subscriber", - "upload-complete", - "upload-get", - "url", - "user-get", - "user-identity-get", - "user-team-list", - "uuid", -] - -[[package]] -name = "api-group" -version = "25.5.2" -dependencies = [ - "api-helper", - "async-trait", - "chirp-client", - "chrono", - "faker-user", - "futures-util", - "game-get", - "game-resolve-namespace-id", - "http 0.2.12", - "hyper 0.14.31", - "lazy_static", - "prost 0.10.4", - "rand 0.8.5", - "rivet-api", - "rivet-cache", - "rivet-claims", - "rivet-config", - "rivet-connection", - "rivet-convert", - "rivet-env", - "rivet-group", - "rivet-group-server", - "rivet-health-checks", - "rivet-operation", - "rivet-pools", - "serde", - "serde_json", - "team-avatar-upload-complete", - "team-get", - "team-invite-get", - "team-join-request-list", - "team-member-count", - "team-member-list", - "team-profile-validate", - "team-recommend", - "team-user-ban-get", - "team-user-ban-list", - "thiserror 1.0.69", - "token-revoke", - "tokio", - "tracing", - "tracing-subscriber", - "upload-prepare", - "url", - "user-get", - "user-identity-get", - "user-team-list", - "user-token-create", - "uuid", -] - -[[package]] -name = "api-helper" -version = "25.5.2" -dependencies = [ - "api-helper-macros", - "async-trait", - "chirp-client", - "chirp-worker", - "chirp-workflow", - "chrono", - "formatted-error", - "futures-util", - "global-error", - "headers", - "http 0.2.12", - "hyper 0.14.31", - "lazy_static", - "opentelemetry 0.28.0", - "opentelemetry-semantic-conventions 0.28.0", - "prost 0.10.4", - "regex", - "reqwest 0.12.12", - "rivet-api", - "rivet-cache", - "rivet-claims", - "rivet-config", - "rivet-connection", - "rivet-env", - "rivet-health-checks", - "rivet-metrics", - "rivet-operation", - "rivet-pools", - "rivet-runtime", - "rivet-util", - "serde", - "serde_array_query", - "serde_json", - "thiserror 1.0.69", - "tokio", - "tracing", - "tracing-opentelemetry", - "tracing-subscriber", - "types-proto", - "url", - "uuid", -] - -[[package]] -name = "api-helper-macros" -version = "25.5.2" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "api-identity" -version = "25.5.2" -dependencies = [ - "api-helper", - "async-trait", - "cdn-namespace-domain-create", - "cdn-namespace-get", - "chirp-client", - "cloud-namespace-token-development-create", - "faker-build", - "faker-game", - "faker-game-namespace", - "faker-game-version", - "faker-region", - "faker-user", - "futures-util", - "game-get", - "game-namespace-get", - "game-namespace-resolve-url", - "game-resolve-namespace-id", - "http 0.2.12", - "hyper 0.14.31", - "job-run", - "lazy_static", - "mm-config-lobby-group-resolve-version", - "mm-config-version-get", - "mm-lobby-get", - "prost 0.10.4", - "rand 0.8.5", - "regex", - "region-get", - "rivet-api", - "rivet-cache", - "rivet-claims", - "rivet-config", - "rivet-connection", - "rivet-convert", - "rivet-env", - "rivet-health-checks", - "rivet-identity", - "rivet-operation", - "rivet-pools", - "rivet-util-mm", - "serde", - "serde_json", - "team-recommend", - "thiserror 1.0.69", - "token-create", - "token-get", - "token-revoke", - "tokio", - "tracing", - "tracing-subscriber", - "upload-prepare", - "url", - "user-avatar-upload-complete", - "user-get", - "user-identity-get", - "user-pending-delete-toggle", - "user-profile-validate", - "uuid", -] - -[[package]] -name = "api-job" -version = "25.5.2" -dependencies = [ - "api-helper", - "async-trait", - "chirp-client", - "chrono", - "faker-job-run", - "http 0.2.12", - "hyper 0.14.31", - "job-run", - "lazy_static", - "nomad-client", - "nomad-util", - "prost 0.10.4", - "reqwest 0.11.27", - "rivet-cache", - "rivet-claims", - "rivet-config", - "rivet-connection", - "rivet-env", - "rivet-health-checks", - "rivet-job", - "rivet-job-server", - "rivet-operation", - "rivet-pools", - "serde", - "serde_json", - "thiserror 1.0.69", - "token-create", - "tokio", - "tracing", - "tracing-subscriber", - "url", - "uuid", -] - -[[package]] -name = "api-matchmaker" -version = "25.5.2" -dependencies = [ - "api-helper", - "async-trait", - "bytes", - "captcha-hcaptcha-config-get", - "captcha-request", - "captcha-turnstile-config-get", - "captcha-verify", - "cdn-namespace-domain-create", - "cdn-namespace-get", - "chirp-client", - "chrono", - "cloud-namespace-token-development-create", - "cloud-namespace-token-public-create", - "faker-build", - "faker-game", - "faker-game-namespace", - "faker-game-version", - "faker-region", - "game-get", - "game-namespace-get", - "game-namespace-resolve-url", - "game-resolve-namespace-id", - "http 0.2.12", - "hyper 0.14.31", - "job-run", - "lazy_static", - "mm-config-lobby-group-resolve-version", - "mm-config-version-get", - "mm-dev-player-token-create", - "mm-lobby-get", - "mm-lobby-list-for-namespace", - "mm-lobby-player-count", - "mm-lobby-state-get", - "prost 0.10.4", - "region-get", - "region-recommend", - "region-resolve-for-game", - "reqwest 0.11.27", - "rivet-api", - "rivet-cache", - "rivet-claims", - "rivet-config", - "rivet-connection", - "rivet-convert", - "rivet-env", - "rivet-health-checks", - "rivet-matchmaker-server", - "rivet-operation", - "rivet-pools", - "rivet-util-job", - "rivet-util-mm", - "serde", - "serde_json", - "thiserror 1.0.69", - "token-create", - "token-revoke", - "tokio", - "tracing", - "tracing-subscriber", - "url", - "user-identity-get", - "uuid", -] - -[[package]] -name = "api-portal" -version = "25.5.2" -dependencies = [ - "api-helper", - "async-trait", - "chirp-client", - "chrono", - "faker-user", - "futures-util", - "game-get", - "game-resolve-name-id", - "http 0.2.12", - "hyper 0.14.31", - "lazy_static", - "prost 0.10.4", - "rand 0.8.5", - "regex", - "rivet-cache", - "rivet-claims", - "rivet-config", - "rivet-connection", - "rivet-convert", - "rivet-env", - "rivet-health-checks", - "rivet-operation", - "rivet-pools", - "rivet-portal", - "rivet-portal-server", - "serde", - "serde_json", - "team-get", - "team-member-count", - "thiserror 1.0.69", - "token-revoke", - "tokio", - "tracing", - "tracing-subscriber", - "url", - "user-get", - "user-team-list", - "user-token-create", - "uuid", -] - -[[package]] -name = "api-provision" -version = "25.5.2" -dependencies = [ - "api-helper", - "async-trait", - "chirp-client", - "chrono", - "cluster", - "http 0.2.12", - "hyper 0.14.31", - "lazy_static", - "prost 0.10.4", - "rivet-api", - "rivet-cache", - "rivet-claims", - "rivet-config", - "rivet-convert", - "rivet-env", - "rivet-health-checks", - "rivet-operation", - "rivet-pools", - "serde", - "serde_json", - "thiserror 1.0.69", - "tokio", - "tracing", - "tracing-subscriber", - "url", - "uuid", -] - -[[package]] -name = "api-status" -version = "25.5.2" -dependencies = [ - "api-helper", - "async-trait", - "async_once", - "chirp-client", - "chrono", - "cluster", - "faker-region", - "futures-util", - "game-namespace-resolve-name-id", - "game-resolve-name-id", - "http 0.2.12", - "hyper 0.14.31", - "lazy_static", - "prost 0.10.4", - "regex", - "reqwest 0.11.27", - "rivet-api", - "rivet-cache", - "rivet-claims", - "rivet-config", - "rivet-connection", - "rivet-env", - "rivet-health-checks", - "rivet-matchmaker", - "rivet-operation", - "rivet-pools", - "rivet-status", - "rivet-status-server", - "s3-util", - "serde", - "serde_json", - "thiserror 1.0.69", - "token-create", - "tokio", - "tokio-tungstenite 0.21.0", - "tracing", - "tracing-subscriber", - "url", - "urlencoding", - "uuid", -] - -[[package]] -name = "api-ui" -version = "25.5.2" -dependencies = [ - "api-helper", - "async-trait", - "chirp-client", - "chrono", - "global-error", - "headers", - "http 0.2.12", - "hyper 0.14.31", - "lazy_static", - "prost 0.10.4", - "reqwest 0.12.12", - "rivet-auth-server", - "rivet-cache", - "rivet-claims", - "rivet-config", - "rivet-convert", - "rivet-health-checks", - "rivet-operation", - "rivet-pools", - "serde", - "serde_json", - "thiserror 1.0.69", - "tokio", - "tracing", - "tracing-subscriber", - "url", - "uuid", -] - -[[package]] -name = "approx" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" -dependencies = [ - "num-traits", -] - -[[package]] -name = "arc-swap" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" - -[[package]] -name = "arraydeque" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" - -[[package]] -name = "arrayref" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" - -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" -dependencies = [ - "serde", -] - -[[package]] -name = "ascii" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" - -[[package]] -name = "ash" -version = "0.37.3+1.3.251" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a" -dependencies = [ - "libloading 0.7.4", -] - -[[package]] -name = "asn1-rs" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" -dependencies = [ - "asn1-rs-derive", - "asn1-rs-impl", - "displaydoc", - "nom 7.1.3", - "num-traits", - "rusticata-macros", - "thiserror 1.0.69", - "time 0.3.37", -] - -[[package]] -name = "asn1-rs-derive" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "synstructure 0.12.6", -] - -[[package]] -name = "asn1-rs-impl" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "assert_cmd" -version = "2.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1835b7f27878de8525dc71410b5a31cdcc5f230aed5ba5df968e09c201b23d" -dependencies = [ - "anstyle", - "bstr", - "doc-comment", - "libc", - "predicates", - "predicates-core", - "predicates-tree", - "wait-timeout", -] - -[[package]] -name = "ast_node" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9184f2b369b3e8625712493c89b785881f27eedc6cde480a81883cef78868b2" -dependencies = [ - "proc-macro2", - "quote", - "swc_macros_common", - "syn 2.0.90", -] - -[[package]] -name = "async-channel" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" -dependencies = [ - "concurrent-queue", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-compression" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df895a515f70646414f4b45c0b79082783b80552b373a68283012928df56f522" -dependencies = [ - "brotli 7.0.0", - "flate2", - "futures-core", - "memchr", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "async-lock" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" -dependencies = [ - "event-listener", - "event-listener-strategy", - "pin-project-lite", -] - -[[package]] -name = "async-nats" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc1f1a75fd07f0f517322d103211f12d757658e91676def9a2e688774656c60" -dependencies = [ - "base64 0.21.7", - "bytes", - "futures", - "http 0.2.12", - "memchr", - "nkeys", - "nuid", - "once_cell", - "rand 0.8.5", - "regex", - "ring 0.17.8", - "rustls 0.21.12", - "rustls-native-certs 0.6.3", - "rustls-pemfile 1.0.4", - "rustls-webpki 0.101.7", - "serde", - "serde_json", - "serde_nanos", - "serde_repr", - "thiserror 1.0.69", - "time 0.3.37", - "tokio", - "tokio-retry", - "tokio-rustls 0.24.1", - "tracing", - "url", -] - -[[package]] -name = "async-posthog" -version = "0.2.3" -source = "git+https://github.com/rivet-gg/posthog-rs?rev=ef4e80e#ef4e80e57747ea7204794bce9a103bfeccefabf1" -dependencies = [ - "posthog-core", - "reqwest 0.11.27", - "serde", - "serde_json", - "thiserror 1.0.69", - "tokio", -] - -[[package]] -name = "async-recursion" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "async-stream" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "async-trait" -version = "0.1.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "async_once" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ce4f10ea3abcd6617873bae9f91d1c5332b4a778bd9ce34d0cd517474c1de82" - -[[package]] -name = "atoi" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" -dependencies = [ - "num-traits", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[package]] -name = "autotools" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef941527c41b0fc0dd48511a8154cd5fc7e29200a0ff8b7203c5d777dbc795cf" -dependencies = [ - "cc", -] - -[[package]] -name = "aws-credential-types" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60e8f6b615cb5fc60a98132268508ad104310f0cfb25a1c22eee76efdf9154da" -dependencies = [ - "aws-smithy-async 1.2.1", - "aws-smithy-runtime-api", - "aws-smithy-types 1.2.9", - "zeroize", -] - -[[package]] -name = "aws-lc-rs" -version = "1.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dabb68eb3a7aa08b46fddfd59a3d55c978243557a90ab804769f7e20e67d2b01" -dependencies = [ - "aws-lc-sys", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77926887776171ced7d662120a75998e444d3750c951abfe07f90da130514b1f" -dependencies = [ - "bindgen 0.69.5", - "cc", - "cmake", - "dunce", - "fs_extra", -] - -[[package]] -name = "aws-runtime" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a10d5c055aa540164d9561a0e2e74ad30f0dcf7393c3a92f6733ddf9c5762468" -dependencies = [ - "aws-credential-types", - "aws-sigv4", - "aws-smithy-async 1.2.1", - "aws-smithy-eventstream", - "aws-smithy-http 0.60.11", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types 1.2.9", - "aws-types", - "bytes", - "fastrand 2.2.0", - "http 0.2.12", - "http-body 0.4.6", - "once_cell", - "percent-encoding", - "pin-project-lite", - "tracing", - "uuid", -] - -[[package]] -name = "aws-sdk-s3" -version = "1.63.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43850204a109a5eea1ea93951cf0440268cef98b0d27dfef4534949e23735f7" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-sigv4", - "aws-smithy-async 1.2.1", - "aws-smithy-checksums", - "aws-smithy-eventstream", - "aws-smithy-http 0.60.11", - "aws-smithy-json 0.60.7", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types 1.2.9", - "aws-smithy-xml", - "aws-types", - "bytes", - "fastrand 2.2.0", - "hex", - "hmac 0.12.1", - "http 0.2.12", - "http-body 0.4.6", - "lru", - "once_cell", - "percent-encoding", - "regex-lite", - "sha2 0.10.8", - "tracing", - "url", -] - -[[package]] -name = "aws-sigv4" -version = "1.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5619742a0d8f253be760bfbb8e8e8368c69e3587e4637af5754e488a611499b1" -dependencies = [ - "aws-credential-types", - "aws-smithy-eventstream", - "aws-smithy-http 0.60.11", - "aws-smithy-runtime-api", - "aws-smithy-types 1.2.9", - "bytes", - "crypto-bigint 0.5.5", - "form_urlencoded", - "hex", - "hmac 0.12.1", - "http 0.2.12", - "http 1.1.0", - "once_cell", - "p256 0.11.1", - "percent-encoding", - "ring 0.17.8", - "sha2 0.10.8", - "subtle", - "time 0.3.37", - "tracing", - "zeroize", -] - -[[package]] -name = "aws-smithy-async" -version = "0.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dcbf7d119f514a627d236412626645c4378b126e30dc61db9de3e069fa1676" -dependencies = [ - "futures-util", - "pin-project-lite", - "tokio", - "tokio-stream", -] - -[[package]] -name = "aws-smithy-async" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62220bc6e97f946ddd51b5f1361f78996e704677afc518a4ff66b7a72ea1378c" -dependencies = [ - "futures-util", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "aws-smithy-checksums" -version = "0.60.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1a71073fca26775c8b5189175ea8863afb1c9ea2cceb02a5de5ad9dfbaa795" -dependencies = [ - "aws-smithy-http 0.60.11", - "aws-smithy-types 1.2.9", - "bytes", - "crc32c", - "crc32fast", - "hex", - "http 0.2.12", - "http-body 0.4.6", - "md-5", - "pin-project-lite", - "sha1", - "sha2 0.10.8", - "tracing", -] - -[[package]] -name = "aws-smithy-client" -version = "0.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "511ac6c65f2a89cfcd74fe78aa6d07216095a53cbaeab493b17f6df82cd65b86" -dependencies = [ - "aws-smithy-async 0.41.0", - "aws-smithy-http 0.41.0", - "aws-smithy-http-tower", - "aws-smithy-types 0.41.0", - "bytes", - "fastrand 1.9.0", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.31", - "hyper-rustls 0.22.1", - "hyper-tls 0.5.0", - "lazy_static", - "pin-project", - "pin-project-lite", - "tokio", - "tower 0.4.13", - "tracing", -] - -[[package]] -name = "aws-smithy-eventstream" -version = "0.60.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cef7d0a272725f87e51ba2bf89f8c21e4df61b9e49ae1ac367a6d69916ef7c90" -dependencies = [ - "aws-smithy-types 1.2.9", - "bytes", - "crc32fast", -] - -[[package]] -name = "aws-smithy-http" -version = "0.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d800c8684fa567cdf1abd9654c7997b2a887e7b06022938756193472ec7ec251" -dependencies = [ - "aws-smithy-types 0.41.0", - "bytes", - "bytes-utils", - "futures-core", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.31", - "once_cell", - "percent-encoding", - "pin-project", - "tokio", - "tokio-util 0.6.10", - "tracing", -] - -[[package]] -name = "aws-smithy-http" -version = "0.60.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8bc3e8fdc6b8d07d976e301c02fe553f72a39b7a9fea820e023268467d7ab6" -dependencies = [ - "aws-smithy-eventstream", - "aws-smithy-runtime-api", - "aws-smithy-types 1.2.9", - "bytes", - "bytes-utils", - "futures-core", - "http 0.2.12", - "http-body 0.4.6", - "once_cell", - "percent-encoding", - "pin-project-lite", - "pin-utils", - "tracing", -] - -[[package]] -name = "aws-smithy-http-tower" -version = "0.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8017959786cce64e690214d303d062c97fcd38a68df7cb444255e534c9bbce49" -dependencies = [ - "aws-smithy-http 0.41.0", - "bytes", - "http 0.2.12", - "http-body 0.4.6", - "pin-project", - "tower 0.4.13", - "tracing", -] - -[[package]] -name = "aws-smithy-json" -version = "0.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3796e2a4a3b7d15db2fd5aec2de9220919332648f0a56a77b5c53caf4a9653fa" -dependencies = [ - "aws-smithy-types 0.41.0", -] - -[[package]] -name = "aws-smithy-json" -version = "0.60.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4683df9469ef09468dad3473d129960119a0d3593617542b7d52086c8486f2d6" -dependencies = [ - "aws-smithy-types 1.2.9", -] - -[[package]] -name = "aws-smithy-runtime" -version = "1.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be28bd063fa91fd871d131fc8b68d7cd4c5fa0869bea68daca50dcb1cbd76be2" -dependencies = [ - "aws-smithy-async 1.2.1", - "aws-smithy-http 0.60.11", - "aws-smithy-runtime-api", - "aws-smithy-types 1.2.9", - "bytes", - "fastrand 2.2.0", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "http-body 1.0.1", - "httparse", - "hyper 0.14.31", - "hyper-rustls 0.24.2", - "once_cell", - "pin-project-lite", - "pin-utils", - "rustls 0.21.12", - "tokio", - "tracing", -] - -[[package]] -name = "aws-smithy-runtime-api" -version = "1.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92165296a47a812b267b4f41032ff8069ab7ff783696d217f0994a0d7ab585cd" -dependencies = [ - "aws-smithy-async 1.2.1", - "aws-smithy-types 1.2.9", - "bytes", - "http 0.2.12", - "http 1.1.0", - "pin-project-lite", - "tokio", - "tracing", - "zeroize", -] - -[[package]] -name = "aws-smithy-types" -version = "0.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c7f957a2250cc0fa4ccf155e00aeac9a81f600df7cd4ecc910c75030e6534f5" -dependencies = [ - "itoa 1.0.14", - "num-integer", - "ryu", - "time 0.3.37", -] - -[[package]] -name = "aws-smithy-types" -version = "1.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbd94a32b3a7d55d3806fe27d98d3ad393050439dd05eb53ece36ec5e3d3510" -dependencies = [ - "base64-simd 0.8.0", - "bytes", - "bytes-utils", - "futures-core", - "http 0.2.12", - "http 1.1.0", - "http-body 0.4.6", - "http-body 1.0.1", - "http-body-util", - "itoa 1.0.14", - "num-integer", - "pin-project-lite", - "pin-utils", - "ryu", - "serde", - "time 0.3.37", - "tokio", - "tokio-util 0.7.12", -] - -[[package]] -name = "aws-smithy-xml" -version = "0.60.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab0b0166827aa700d3dc519f72f8b3a91c35d0b8d042dc5d643a91e6f80648fc" -dependencies = [ - "xmlparser", -] - -[[package]] -name = "aws-types" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5221b91b3e441e6675310829fd8984801b772cb1546ef6c0e54dec9f1ac13fef" -dependencies = [ - "aws-credential-types", - "aws-smithy-async 1.2.1", - "aws-smithy-runtime-api", - "aws-smithy-types 1.2.9", - "rustc_version 0.4.1", - "tracing", -] - -[[package]] -name = "axum" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" -dependencies = [ - "async-trait", - "axum-core", - "bytes", - "futures-util", - "http 1.1.0", - "http-body 1.0.1", - "http-body-util", - "itoa 1.0.14", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "sync_wrapper 1.0.2", - "tower 0.5.2", - "tower-layer", - "tower-service", -] - -[[package]] -name = "axum-core" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http 1.1.0", - "http-body 1.0.1", - "http-body-util", - "mime", - "pin-project-lite", - "rustversion", - "sync_wrapper 1.0.2", - "tower-layer", - "tower-service", -] - -[[package]] -name = "az" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" - -[[package]] -name = "backtrace" -version = "0.3.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide 0.8.0", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - -[[package]] -name = "base16ct" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" - -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - -[[package]] -name = "base32" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "022dfe9eb35f19ebbcb51e0b40a5ab759f46ad60cadf7297e0bd085afb50e076" - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "base64-simd" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "781dd20c3aff0bd194fe7d2a977dd92f21c173891f3a03b677359e5fa457e5d5" -dependencies = [ - "simd-abstraction", -] - -[[package]] -name = "base64-simd" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" -dependencies = [ - "outref 0.5.1", - "vsimd", -] - -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - -[[package]] -name = "bcrypt" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7e7c93a3fb23b2fdde989b2c9ec4dd153063ec81f408507f84c090cd91c6641" -dependencies = [ - "base64 0.13.1", - "blowfish", - "getrandom 0.2.15", - "zeroize", -] - -[[package]] -name = "better_scoped_tls" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297b153aa5e573b5863108a6ddc9d5c968bd0b20e75cc614ee9821d2f45679c7" -dependencies = [ - "scoped-tls", -] - -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - -[[package]] -name = "bindgen" -version = "0.69.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" -dependencies = [ - "bitflags 2.6.0", - "cexpr", - "clang-sys", - "itertools 0.12.1", - "lazy_static", - "lazycell", - "log", - "prettyplease 0.2.25", - "proc-macro2", - "quote", - "regex", - "rustc-hash 1.1.0", - "shlex", - "syn 2.0.90", - "which 4.4.2", -] - -[[package]] -name = "bindgen" -version = "0.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" -dependencies = [ - "bitflags 2.6.0", - "cexpr", - "clang-sys", - "itertools 0.12.1", - "log", - "prettyplease 0.2.25", - "proc-macro2", - "quote", - "regex", - "rustc-hash 1.1.0", - "shlex", - "syn 2.0.90", -] - -[[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" -dependencies = [ - "serde", -] - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty 2.0.0", - "radium", - "tap", - "wyz", -] - -[[package]] -name = "blake2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "blake3" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8ee0c1824c4dea5b5f81736aff91bae041d2c07ee1192bec91054e10e3e601e" -dependencies = [ - "arrayref", - "arrayvec 0.7.6", - "cc", - "cfg-if", - "constant_time_eq", -] - -[[package]] -name = "block" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-padding" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block2" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" -dependencies = [ - "objc2", -] - -[[package]] -name = "blowfish" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7" -dependencies = [ - "byteorder", - "cipher", -] - -[[package]] -name = "bollard" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ccca1260af6a459d75994ad5acc1651bcabcbdbc41467cc9786519ab854c30" -dependencies = [ - "base64 0.22.1", - "bollard-stubs", - "bytes", - "futures-core", - "futures-util", - "hex", - "home", - "http 1.1.0", - "http-body-util", - "hyper 1.6.0", - "hyper-named-pipe", - "hyper-rustls 0.27.3", - "hyper-util", - "hyperlocal", - "log", - "pin-project-lite", - "rustls 0.23.25", - "rustls-native-certs 0.8.1", - "rustls-pemfile 2.2.0", - "rustls-pki-types", - "serde", - "serde_derive", - "serde_json", - "serde_repr", - "serde_urlencoded", - "thiserror 2.0.12", - "tokio", - "tokio-util 0.7.12", - "tower-service", - "url", - "winapi", -] - -[[package]] -name = "bollard-stubs" -version = "1.47.1-rc.27.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f179cfbddb6e77a5472703d4b30436bff32929c0aa8a9008ecf23d1d3cdd0da" -dependencies = [ - "serde", - "serde_repr", - "serde_with 3.12.0", -] - -[[package]] -name = "boxed_error" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17d4f95e880cfd28c4ca5a006cf7f6af52b4bcb7b5866f573b2faa126fb7affb" -dependencies = [ - "quote", - "syn 2.0.90", -] - -[[package]] -name = "brotli" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli" -version = "7.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli-decompressor" -version = "4.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - -[[package]] -name = "bstr" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22" -dependencies = [ - "memchr", - "regex-automata 0.4.9", - "serde", -] - -[[package]] -name = "build" -version = "25.5.2" -dependencies = [ - "acme-lib", - "anyhow", - "chirp-workflow", - "cjson", - "cloudflare", - "cluster", - "faker-build", - "faker-game", - "faker-region", - "game-get", - "game-namespace-get", - "heck 0.3.3", - "http 0.2.12", - "include_dir", - "indoc 1.0.9", - "ip-info", - "lazy_static", - "linode", - "nomad-client", - "nomad-util", - "rand 0.8.5", - "reqwest 0.12.12", - "rivet-api", - "rivet-convert", - "rivet-metrics", - "rivet-operation", - "rivet-runtime", - "rivet-util-job", - "s3-util", - "serde", - "serde_json", - "sqlx", - "ssh2", - "strum 0.26.3", - "token-create", - "upload-get", - "upload-prepare", -] - -[[package]] -name = "build-create" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-build", - "faker-game", - "faker-user", - "game-get", - "game-namespace-get", - "prost 0.10.4", - "reqwest 0.11.27", - "rivet-operation", - "rivet-util-build", - "sqlx", - "upload-complete", - "upload-get", - "upload-prepare", -] - -[[package]] -name = "build-default-create" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "futures-util", - "indoc 1.0.9", - "prost 0.10.4", - "reqwest 0.11.27", - "rivet-config", - "rivet-connection", - "rivet-operation", - "rivet-pools", - "s3-util", - "sqlx", - "tokio", - "tracing", - "tracing-logfmt", - "tracing-subscriber", - "upload-complete", - "upload-prepare", - "uuid", -] - -[[package]] -name = "build-get" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-build", - "faker-game", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "build-list-for-env" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-build", - "faker-game", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "build-list-for-game" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-build", - "faker-game", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" -dependencies = [ - "allocator-api2", -] - -[[package]] -name = "bytecount" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" - -[[package]] -name = "bytemuck" -version = "1.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" -dependencies = [ - "serde", -] - -[[package]] -name = "bytes-utils" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dafe3a8757b027e2be6e4e5601ed563c55989fcf1546e933c66c8eb3a058d35" -dependencies = [ - "bytes", - "either", -] - -[[package]] -name = "bzip2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" -dependencies = [ - "bzip2-sys", - "libc", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.11+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - -[[package]] -name = "cache_control" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf2a5fb3207c12b5d208ebc145f967fea5cac41a021c37417ccc31ba40f39ee" - -[[package]] -name = "camino" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" -dependencies = [ - "serde", -] - -[[package]] -name = "captcha-hcaptcha-config-get" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "rivet-util-captcha", -] - -[[package]] -name = "captcha-hcaptcha-verify" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "reqwest 0.12.12", - "rivet-operation", - "serde", -] - -[[package]] -name = "captcha-request" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "prost 0.10.4", - "rivet-operation", - "rivet-util-captcha", - "sqlx", -] - -[[package]] -name = "captcha-turnstile-config-get" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "rivet-util-captcha", -] - -[[package]] -name = "captcha-turnstile-verify" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "reqwest 0.12.12", - "rivet-operation", - "serde", -] - -[[package]] -name = "captcha-verify" -version = "25.5.2" -dependencies = [ - "captcha-hcaptcha-config-get", - "captcha-hcaptcha-verify", - "captcha-request", - "captcha-turnstile-verify", - "chirp-client", - "chirp-worker", - "chrono", - "prost 0.10.4", - "reqwest 0.12.12", - "rivet-operation", - "rivet-util-captcha", - "serde_json", -] - -[[package]] -name = "cargo-platform" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo_metadata" -version = "0.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8769706aad5d996120af43197bf46ef6ad0fda35216b4505f926a365a232d924" -dependencies = [ - "camino", - "cargo-platform", - "semver 1.0.23", - "serde", - "serde_json", - "thiserror 2.0.12", -] - -[[package]] -name = "cbc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" -dependencies = [ - "cipher", -] - -[[package]] -name = "cc" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" -dependencies = [ - "jobserver", - "libc", - "shlex", -] - -[[package]] -name = "cdn-namespace-auth-user-remove" -version = "25.5.2" -dependencies = [ - "cdn-namespace-auth-user-update", - "cdn-namespace-create", - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "cdn-namespace-auth-user-update" -version = "25.5.2" -dependencies = [ - "cdn-namespace-create", - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "cdn-namespace-create" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "cdn-namespace-domain-create" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "game-get", - "game-resolve-namespace-id", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "cdn-namespace-domain-remove" -version = "25.5.2" -dependencies = [ - "cdn-namespace-domain-create", - "chirp-client", - "chirp-worker", - "faker-game", - "game-get", - "game-resolve-namespace-id", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "cdn-namespace-get" -version = "25.5.2" -dependencies = [ - "cdn-namespace-create", - "cdn-namespace-domain-create", - "cdn-namespace-get", - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "cdn-namespace-resolve-domain" -version = "25.5.2" -dependencies = [ - "cdn-namespace-domain-create", - "chirp-client", - "chirp-worker", - "faker-game", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "cdn-ns-auth-type-set" -version = "25.5.2" -dependencies = [ - "cdn-namespace-create", - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "cdn-ns-enable-domain-public-auth-set" -version = "25.5.2" -dependencies = [ - "cdn-namespace-create", - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "cdn-site-create" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "game-get", - "prost 0.10.4", - "reqwest 0.11.27", - "rivet-operation", - "sqlx", - "upload-complete", - "upload-get", - "upload-prepare", -] - -[[package]] -name = "cdn-site-get" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-cdn-site", - "faker-game", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "cdn-site-list-for-game" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-cdn-site", - "faker-game", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "cdn-version-get" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "faker-game-version", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "cdn-version-prepare" -version = "25.5.2" -dependencies = [ - "cdn-site-get", - "chirp-client", - "chirp-worker", - "faker-cdn-site", - "faker-game", - "prost 0.10.4", - "rivet-operation", - "upload-get", -] - -[[package]] -name = "cdn-version-publish" -version = "25.5.2" -dependencies = [ - "cdn-version-get", - "chirp-client", - "chirp-worker", - "faker-cdn-site", - "faker-game", - "itertools 0.10.5", - "prost 0.10.4", - "rivet-operation", - "sqlx", - "unzip-n", -] - -[[package]] -name = "cdn-worker" -version = "25.5.2" -dependencies = [ - "cdn-namespace-get", - "cdn-site-get", - "cdn-version-get", - "chirp-client", - "chirp-worker", - "game-get", - "game-namespace-get", - "rivet-config", - "rivet-health-checks", - "rivet-metrics", - "rivet-runtime", - "rivet-util-cdn", - "upload-get", -] - -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom 7.1.3", -] - -[[package]] -name = "cf-custom-hostname-get" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "cf-custom-hostname-list-for-namespace-id" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "cf-custom-hostname-resolve-hostname" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "cf-custom-hostname-worker" -version = "25.5.2" -dependencies = [ - "cf-custom-hostname-get", - "cf-custom-hostname-list-for-namespace-id", - "cf-custom-hostname-resolve-hostname", - "chirp-client", - "chirp-worker", - "faker-game", - "game-get", - "game-list-for-team", - "game-namespace-list", - "game-resolve-namespace-id", - "reqwest 0.12.12", - "rivet-config", - "rivet-health-checks", - "rivet-metrics", - "rivet-runtime", - "serde", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - -[[package]] -name = "chirp-client" -version = "25.5.2" -dependencies = [ - "chirp-perf", - "chirp-types", - "chrono", - "futures-util", - "global-error", - "lazy_static", - "prost 0.10.4", - "rand 0.8.5", - "rivet-metrics", - "rivet-pools", - "rivet-test-images", - "rivet-util", - "serde", - "testcontainers 0.12.0", - "thiserror 1.0.69", - "tokio", - "tokio-util 0.7.12", - "tracing", - "tracing-subscriber", - "types-proto", - "urlencoding", - "uuid", -] - -[[package]] -name = "chirp-metrics" -version = "25.5.2" -dependencies = [ - "lazy_static", - "rivet-metrics", -] - -[[package]] -name = "chirp-perf" -version = "25.5.2" -dependencies = [ - "lazy_static", - "prost 0.10.4", - "redis", - "rivet-env", - "rivet-metrics", - "rivet-pools", - "thiserror 1.0.69", - "tokio", - "tracing", - "types-proto", - "uuid", -] - -[[package]] -name = "chirp-types" -version = "25.5.2" -dependencies = [ - "prost 0.10.4", -] - -[[package]] -name = "chirp-worker" -version = "25.5.2" -dependencies = [ - "async-trait", - "chirp-client", - "chirp-metrics", - "chirp-perf", - "chirp-worker-attributes", - "formatted-error", - "futures-util", - "global-error", - "indoc 1.0.9", - "lazy_static", - "prost 0.10.4", - "rand 0.8.5", - "redis", - "rivet-cache", - "rivet-config", - "rivet-connection", - "rivet-env", - "rivet-metrics", - "rivet-operation", - "rivet-pools", - "rivet-runtime", - "rivet-test-images", - "rivet-util", - "serde_json", - "testcontainers 0.12.0", - "thiserror 1.0.69", - "tokio", - "tracing", - "tracing-subscriber", - "types-proto", - "url", - "uuid", -] - -[[package]] -name = "chirp-worker-attributes" -version = "25.5.2" -dependencies = [ - "chirp-worker", - "proc-macro2", - "prost 0.10.4", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "chirp-workflow" -version = "25.5.2" -dependencies = [ - "anyhow", - "async-trait", - "chirp-client", - "chirp-workflow-macros", - "cjson", - "dirs", - "fdb-util", - "formatted-error", - "foundationdb", - "futures-util", - "global-error", - "include_dir", - "indoc 2.0.5", - "itertools 0.14.0", - "lazy_static", - "md5", - "opentelemetry 0.28.0", - "prost 0.12.6", - "prost-types 0.12.6", - "rand 0.8.5", - "rivet-cache", - "rivet-config", - "rivet-connection", - "rivet-env", - "rivet-metrics", - "rivet-operation", - "rivet-pools", - "rivet-runtime", - "rivet-util", - "serde", - "serde_json", - "sqlx", - "statrs", - "strum 0.26.3", - "thiserror 1.0.69", - "tokio", - "tokio-util 0.7.12", - "tracing", - "tracing-logfmt", - "tracing-opentelemetry", - "tracing-subscriber", - "url", - "uuid", -] - -[[package]] -name = "chirp-workflow-macros" -version = "25.5.2" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "chrono" -version = "0.4.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-targets 0.52.6", -] - -[[package]] -name = "chunked_transfer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901" - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", -] - -[[package]] -name = "cjson" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91531b1d3fe15c6126decd9977dc823e1fde8e2501cf6ac780407f952a28f7ce" -dependencies = [ - "itoa 0.4.8", - "serde", - "serde_derive", - "serde_json", -] - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading 0.8.6", -] - -[[package]] -name = "clap" -version = "4.5.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e958897981290da2a852763fe9cdb89cd36977a5d729023127095fa94d95e2ff" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.5.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83b0f35019843db2160b5bb19ae09b4e6411ac33fc6a712003c33e03090e2489" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim 0.11.1", - "terminal_size", -] - -[[package]] -name = "clap_derive" -version = "4.5.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "clap_lex" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" - -[[package]] -name = "clickhouse" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0875e527e299fc5f4faba42870bf199a39ab0bb2dbba1b8aef0a2151451130f" -dependencies = [ - "bstr", - "bytes", - "clickhouse-derive", - "clickhouse-rs-cityhash-sys", - "futures", - "hyper 0.14.31", - "hyper-tls 0.5.0", - "lz4", - "sealed", - "serde", - "static_assertions", - "thiserror 1.0.69", - "tokio", - "url", - "uuid", -] - -[[package]] -name = "clickhouse-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18af5425854858c507eec70f7deb4d5d8cec4216fcb086283a78872387281ea5" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals 0.26.0", - "syn 1.0.109", -] - -[[package]] -name = "clickhouse-inserter" -version = "25.5.2" -dependencies = [ - "anyhow", - "async-channel", - "futures", - "global-error", - "reqwest 0.11.27", - "serde", - "serde_json", - "thiserror 1.0.69", - "tokio", - "tokio-util 0.7.12", - "tracing", -] - -[[package]] -name = "clickhouse-rs-cityhash-sys" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4baf9d4700a28d6cb600e17ed6ae2b43298a5245f1f76b4eab63027ebfd592b9" -dependencies = [ - "cc", -] - -[[package]] -name = "clickhouse-user-query" -version = "25.5.2" -dependencies = [ - "clickhouse", - "serde", - "serde_json", - "testcontainers 0.24.0", - "thiserror 1.0.69", - "tokio", -] - -[[package]] -name = "clipboard-win" -version = "5.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892" -dependencies = [ - "error-code", -] - -[[package]] -name = "cloud-default-create" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chirp-workflow", - "cloud-game-config-create", - "cloud-namespace-create", - "cloud-version-publish", - "game-create", - "game-namespace-create", - "game-namespace-resolve-name-id", - "game-resolve-name-id", - "pegboard", - "reqwest 0.11.27", - "rivet-config", - "rivet-connection", - "rivet-operation", - "rivet-pools", - "serde", - "serde_json", - "team-resolve-display-name", - "tokio", - "tracing", - "tracing-logfmt", - "tracing-subscriber", - "user", - "uuid", -] - -[[package]] -name = "cloud-device-link-create" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-claims", - "rivet-operation", - "token-create", -] - -[[package]] -name = "cloud-game-config-create" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "cloud-game-config-get" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "cloud-game-config-create", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "cloud-game-token-create" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "prost 0.10.4", - "rivet-operation", - "sqlx", - "token-create", -] - -[[package]] -name = "cloud-namespace-create" -version = "25.5.2" -dependencies = [ - "cdn-namespace-create", - "chirp-client", - "chirp-worker", - "faker-game", - "game-get", - "game-namespace-create", - "game-namespace-get", - "game-version-create", - "mm-config-namespace-create", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "cloud-namespace-get" -version = "25.5.2" -dependencies = [ - "cdn-namespace-get", - "chirp-client", - "chirp-worker", - "cloud-namespace-create", - "faker-game", - "game-namespace-create", - "game-version-create", - "mm-config-namespace-get", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "cloud-namespace-token-development-create" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "game-namespace-get", - "game-token-development-validate", - "prost 0.10.4", - "rivet-operation", - "sqlx", - "token-create", -] - -[[package]] -name = "cloud-namespace-token-public-create" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "game-namespace-get", - "prost 0.10.4", - "rivet-claims", - "rivet-operation", - "sqlx", - "token-create", -] - -[[package]] -name = "cloud-version-get" -version = "25.5.2" -dependencies = [ - "cdn-version-get", - "chirp-client", - "chirp-worker", - "cloud-version-publish", - "faker-build", - "faker-game", - "faker-region", - "mm-config-version-get", - "prost 0.10.4", - "rivet-operation", - "rivet-util-mm", - "sqlx", -] - -[[package]] -name = "cloud-version-publish" -version = "25.5.2" -dependencies = [ - "cdn-version-prepare", - "cdn-version-publish", - "chirp-client", - "chirp-worker", - "faker-build", - "faker-game", - "game-get", - "game-version-create", - "game-version-validate", - "mm-config-version-prepare", - "mm-config-version-publish", - "prost 0.10.4", - "region-list", - "rivet-operation", - "rivet-util-mm", - "sqlx", -] - -[[package]] -name = "cloud-worker" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "cloud-game-token-create", - "rivet-config", - "rivet-health-checks", - "rivet-metrics", - "rivet-runtime", -] - -[[package]] -name = "cloudflare" -version = "0.13.0" -source = "git+https://github.com/LSilent/cloudflare-rs?rev=b2c6f366ee68a7956fb69dd4f39357b3c184bd15#b2c6f366ee68a7956fb69dd4f39357b3c184bd15" -dependencies = [ - "chrono", - "http 1.1.0", - "percent-encoding", - "reqwest 0.12.12", - "serde", - "serde_json", - "serde_urlencoded", - "serde_with 3.12.0", - "thiserror 2.0.12", - "url", - "uuid", -] - -[[package]] -name = "cluster" -version = "25.5.2" -dependencies = [ - "acme-lib", - "anyhow", - "chirp-workflow", - "chrono", - "cloudflare", - "hex", - "http 1.1.0", - "include_dir", - "indoc 1.0.9", - "ip-info", - "ipnet", - "lazy_static", - "linode", - "merkle_hash", - "nomad-util", - "nomad_client", - "rand 0.8.5", - "reqwest 0.12.12", - "rivet-api", - "rivet-config", - "rivet-metrics", - "rivet-operation", - "rivet-runtime", - "s3-util", - "serde", - "serde_urlencoded", - "serde_yaml", - "server-spec", - "sqlx", - "ssh2", - "strum 0.24.1", - "token-create", - "tokio", - "trust-dns-resolver", - "url", -] - -[[package]] -name = "cluster-datacenter-tls-renew" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-workflow", - "cluster", - "rivet-config", - "rivet-connection", - "rivet-health-checks", - "rivet-metrics", - "rivet-runtime", - "sqlx", - "tokio", - "tracing", - "tracing-logfmt", - "tracing-subscriber", -] - -[[package]] -name = "cluster-default-update" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chirp-workflow", - "cluster", - "reqwest 0.11.27", - "rivet-config", - "rivet-connection", - "rivet-pools", - "serde", - "serde_json", - "tokio", - "tracing", - "tracing-logfmt", - "tracing-subscriber", - "uuid", -] - -[[package]] -name = "cluster-gc" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-workflow", - "cluster", - "rivet-config", - "rivet-connection", - "rivet-health-checks", - "rivet-metrics", - "rivet-runtime", - "sqlx", - "tokio", - "tracing", - "tracing-logfmt", - "tracing-subscriber", -] - -[[package]] -name = "cluster-metrics-publish" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-workflow", - "cluster", - "rivet-config", - "rivet-connection", - "rivet-health-checks", - "rivet-metrics", - "rivet-runtime", - "sqlx", - "strum 0.26.3", - "tokio", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "cmake" -version = "0.1.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" -dependencies = [ - "cc", -] - -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width 0.1.14", -] - -[[package]] -name = "color-print" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3aa954171903797d5623e047d9ab69d91b493657917bdfb8c2c80ecaf9cdb6f4" -dependencies = [ - "color-print-proc-macro", -] - -[[package]] -name = "color-print-proc-macro" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692186b5ebe54007e45a59aea47ece9eb4108e141326c304cdc91699a7118a22" -dependencies = [ - "nom 7.1.3", - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "color_quant" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" - -[[package]] -name = "colorchoice" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" - -[[package]] -name = "colored_json" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e35980a1b846f8e3e359fd18099172a0857140ba9230affc4f71348081e039b6" -dependencies = [ - "serde", - "serde_json", - "yansi", -] - -[[package]] -name = "combine" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" -dependencies = [ - "bytes", - "futures-core", - "memchr", - "pin-project-lite", - "tokio", - "tokio-util 0.7.12", -] - -[[package]] -name = "concurrent-queue" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "condtype" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf0a07a401f374238ab8e2f11a104d2851bf9ce711ec69804834de8af45c7af" - -[[package]] -name = "config" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68578f196d2a33ff61b27fae256c3164f65e36382648e30666dde05b8cc9dfdf" -dependencies = [ - "async-trait", - "nom 7.1.3", - "pathdiff", - "serde", - "serde_json", - "yaml-rust2", -] - -[[package]] -name = "console" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" -dependencies = [ - "encode_unicode", - "lazy_static", - "libc", - "unicode-width 0.1.14", - "windows-sys 0.52.0", -] - -[[package]] -name = "console-api" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8030735ecb0d128428b64cd379809817e620a40e5001c54465b99ec5feec2857" -dependencies = [ - "futures-core", - "prost 0.13.4", - "prost-types 0.13.4", - "tonic", - "tracing-core", -] - -[[package]] -name = "console-subscriber" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6539aa9c6a4cd31f4b1c040f860a1eac9aa80e7df6b05d506a6e7179936d6a01" -dependencies = [ - "console-api", - "crossbeam-channel", - "crossbeam-utils", - "futures-task", - "hdrhistogram", - "humantime", - "hyper-util", - "prost 0.13.4", - "prost-types 0.13.4", - "serde", - "serde_json", - "thread_local", - "tokio", - "tokio-stream", - "tonic", - "tracing", - "tracing-core", - "tracing-subscriber", -] - -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] - -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "const_format" -version = "0.2.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c655d81ff1114fb0dcdea9225ea9f0cc712a6f8d189378e82bdf62a473a64b" -dependencies = [ - "const_format_proc_macros", -] - -[[package]] -name = "const_format_proc_macros" -version = "0.2.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff1a44b93f47b1bac19a27932f5c591e43d1ba357ee4f61526c8a25603f0eb1" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "constant_time_eq" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" - -[[package]] -name = "cooked-waker" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147be55d677052dabc6b22252d5dd0fd4c29c8c27aa4f2fbef0f94aa003b406f" - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "core-graphics-types" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" -dependencies = [ - "bitflags 1.3.2", - "core-foundation 0.9.4", - "libc", -] - -[[package]] -name = "core-guard" -version = "0.1.0" -dependencies = [ - "chirp-workflow", - "clickhouse-user-query", - "indoc 2.0.5", - "once_cell", - "rivet-operation", - "serde", -] - -[[package]] -name = "cpufeatures" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" -dependencies = [ - "libc", -] - -[[package]] -name = "crc" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" - -[[package]] -name = "crc32c" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a47af21622d091a8f0fb295b88bc886ac74efcc613efc19f5d0b21de5c89e47" -dependencies = [ - "rustc_version 0.4.1", -] - -[[package]] -name = "crc32fast" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "croner" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38fd53511eaf0b00a185613875fee58b208dfce016577d0ad4bb548e1c4fb3ee" -dependencies = [ - "chrono", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" - -[[package]] -name = "crossterm" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" -dependencies = [ - "bitflags 1.3.2", - "crossterm_winapi", - "libc", - "mio 0.8.11", - "parking_lot 0.12.3", - "signal-hook", - "signal-hook-mio", - "winapi", -] - -[[package]] -name = "crossterm_winapi" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" -dependencies = [ - "winapi", -] - -[[package]] -name = "crypto-bigint" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "typenum", -] - -[[package]] -name = "crypto-mac" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4857fd85a0c34b3c3297875b747c1e02e06b6a0ea32dd892d8192b9ce0813ea6" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "csv" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" -dependencies = [ - "csv-core", - "itoa 1.0.14", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" -dependencies = [ - "memchr", -] - -[[package]] -name = "ct-logs" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1a816186fa68d9e426e3cb4ae4dff1fcd8e4a2c34b781bf7a822574a0d0aac8" -dependencies = [ - "sct 0.6.1", -] - -[[package]] -name = "ctr" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" -dependencies = [ - "cipher", -] - -[[package]] -name = "ctrlc" -version = "3.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3" -dependencies = [ - "nix 0.29.0", - "windows-sys 0.59.0", -] - -[[package]] -name = "curve25519-dalek" -version = "4.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" -dependencies = [ - "cfg-if", - "cpufeatures", - "curve25519-dalek-derive", - "digest 0.10.7", - "fiat-crypto 0.2.9", - "rustc_version 0.4.1", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "custom-user-avatar-list-for-game" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "custom-user-avatar-upload-complete", - "faker-game", - "prost 0.10.4", - "reqwest 0.11.27", - "rivet-operation", - "sqlx", - "upload-prepare", -] - -[[package]] -name = "custom-user-avatar-upload-complete" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "reqwest 0.11.27", - "rivet-operation", - "sqlx", - "upload-complete", - "upload-get", - "upload-prepare", -] - -[[package]] -name = "d3d12" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b28bfe653d79bd16c77f659305b195b82bb5ce0c0eb2a4846b82ddbd77586813" -dependencies = [ - "bitflags 2.6.0", - "libloading 0.8.6", - "winapi", -] - -[[package]] -name = "darling" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" -dependencies = [ - "darling_core 0.14.4", - "darling_macro 0.14.4", -] - -[[package]] -name = "darling" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" -dependencies = [ - "darling_core 0.20.10", - "darling_macro 0.20.10", -] - -[[package]] -name = "darling_core" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim 0.10.0", - "syn 1.0.109", -] - -[[package]] -name = "darling_core" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim 0.11.1", - "syn 2.0.90", -] - -[[package]] -name = "darling_macro" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" -dependencies = [ - "darling_core 0.14.4", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "darling_macro" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" -dependencies = [ - "darling_core 0.20.10", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "dashmap" -version = "5.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" -dependencies = [ - "cfg-if", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core 0.9.10", -] - -[[package]] -name = "data-encoding" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" - -[[package]] -name = "data-url" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41b319d1b62ffbd002e057f36bebd1f42b9f97927c9577461d855f3513c4289f" - -[[package]] -name = "debug-email-res" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "email-verification-create", - "prost 0.10.4", - "rand 0.8.5", - "rivet-operation", - "serde_json", - "sqlx", -] - -[[package]] -name = "debugid" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" -dependencies = [ - "serde", - "uuid", -] - -[[package]] -name = "deno-embed" -version = "25.5.2" -dependencies = [ - "anyhow", - "dirs", - "reqwest 0.12.12", - "serde_json", - "tempfile", - "tokio", - "zip", -] - -[[package]] -name = "deno_ast" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b9d03b1bbeeecdac54367f075d572131736d06c5be3bc49037855bc5ab1bbb" -dependencies = [ - "deno_media_type 0.1.4", - "deno_terminal 0.1.1", - "dprint-swc-ext", - "once_cell", - "percent-encoding", - "serde", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_parser", - "swc_eq_ignore_macros", - "text_lines", - "thiserror 1.0.69", - "unicode-width 0.1.14", - "url", -] - -[[package]] -name = "deno_ast" -version = "0.44.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eebc7aaabfdb3ddcad32aee1b62d250149dc8b35dfbdccbb125df2bdc62da952" -dependencies = [ - "base64 0.21.7", - "deno_error", - "deno_media_type 0.2.2", - "deno_terminal 0.2.0", - "dprint-swc-ext", - "once_cell", - "percent-encoding", - "serde", - "sourcemap 9.1.2", - "swc_atoms", - "swc_common", - "swc_config", - "swc_config_macro", - "swc_ecma_ast", - "swc_ecma_codegen", - "swc_ecma_codegen_macros", - "swc_ecma_loader", - "swc_ecma_parser", - "swc_ecma_transforms_base", - "swc_ecma_transforms_classes", - "swc_ecma_transforms_macros", - "swc_ecma_transforms_proposal", - "swc_ecma_transforms_react", - "swc_ecma_transforms_typescript", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_eq_ignore_macros", - "swc_macros_common", - "swc_visit", - "swc_visit_macros", - "text_lines", - "thiserror 2.0.12", - "unicode-width 0.1.14", - "url", -] - -[[package]] -name = "deno_broadcast_channel" -version = "0.174.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "async-trait", - "deno_core", - "thiserror 1.0.69", - "tokio", - "uuid", -] - -[[package]] -name = "deno_cache" -version = "0.112.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "async-trait", - "deno_core", - "rusqlite", - "serde", - "sha2 0.10.8", - "thiserror 1.0.69", - "tokio", -] - -[[package]] -name = "deno_canvas" -version = "0.49.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "deno_core", - "deno_webgpu", - "image", - "serde", - "thiserror 1.0.69", -] - -[[package]] -name = "deno_console" -version = "0.180.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "deno_core", -] - -[[package]] -name = "deno_core" -version = "0.323.0" -source = "git+https://github.com/rivet-gg/deno_core?rev=8a313913fa73d58f4f9532565b0084e723bc34ad#8a313913fa73d58f4f9532565b0084e723bc34ad" -dependencies = [ - "anyhow", - "az", - "bincode", - "bit-set", - "bit-vec", - "bytes", - "cooked-waker", - "deno_core_icudata", - "deno_ops", - "deno_unsync", - "futures", - "indexmap 2.7.0", - "libc", - "memoffset", - "parking_lot 0.12.3", - "percent-encoding", - "pin-project", - "serde", - "serde_json", - "serde_v8", - "smallvec", - "sourcemap 8.0.1", - "static_assertions", - "tokio", - "url", - "v8", - "wasm_dep_analyzer", -] - -[[package]] -name = "deno_core_icudata" -version = "0.74.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4dccb6147bb3f3ba0c7a48e993bfeb999d2c2e47a81badee80e2b370c8d695" - -[[package]] -name = "deno_cron" -version = "0.60.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "anyhow", - "async-trait", - "chrono", - "deno_core", - "saffron", - "thiserror 1.0.69", - "tokio", -] - -[[package]] -name = "deno_crypto" -version = "0.194.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "aes", - "aes-gcm", - "aes-kw", - "base64 0.21.7", - "cbc", - "const-oid", - "ctr", - "curve25519-dalek", - "deno_core", - "deno_web", - "ed448-goldilocks", - "elliptic-curve 0.13.8", - "num-traits", - "once_cell", - "p256 0.13.2", - "p384", - "p521", - "rand 0.8.5", - "ring 0.17.8", - "rsa", - "sec1 0.7.3", - "serde", - "serde_bytes", - "sha1", - "sha2 0.10.8", - "signature 2.2.0", - "spki 0.7.3", - "thiserror 1.0.69", - "tokio", - "uuid", - "x25519-dalek", -] - -[[package]] -name = "deno_error" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "199c66ffd17ee1a948904d33f3d3f364573951c1f9fb3f859bfe7770bf33862a" -dependencies = [ - "deno_error_macro", - "libc", - "serde", - "serde_json", -] - -[[package]] -name = "deno_error_macro" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cd99df6ae75443907e1f959fc42ec6dcea67a7bd083e76cf23a117102c9a2ce" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "deno_fetch" -version = "0.204.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "base64 0.21.7", - "bytes", - "data-url", - "deno_core", - "deno_permissions", - "deno_tls", - "dyn-clone", - "error_reporter", - "hickory-resolver", - "http 1.1.0", - "http-body-util", - "hyper 1.6.0", - "hyper-rustls 0.27.3", - "hyper-util", - "ipnet", - "percent-encoding", - "rustls-webpki 0.102.8", - "serde", - "serde_json", - "thiserror 1.0.69", - "tokio", - "tokio-rustls 0.26.2", - "tokio-socks", - "tokio-util 0.7.12", - "tower 0.4.13", - "tower-http", - "tower-service", -] - -[[package]] -name = "deno_ffi" -version = "0.167.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "deno_core", - "deno_permissions", - "dlopen2 0.6.1", - "dynasmrt", - "libffi", - "libffi-sys", - "log", - "num-bigint", - "serde", - "serde-value", - "serde_json", - "thiserror 1.0.69", - "tokio", - "winapi", -] - -[[package]] -name = "deno_fs" -version = "0.90.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "async-trait", - "base32", - "boxed_error", - "deno_core", - "deno_io", - "deno_path_util", - "deno_permissions", - "filetime", - "junction", - "libc", - "nix 0.27.1", - "rand 0.8.5", - "rayon", - "serde", - "thiserror 1.0.69", - "winapi", - "windows-sys 0.52.0", -] - -[[package]] -name = "deno_http" -version = "0.178.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "async-compression", - "async-trait", - "base64 0.21.7", - "brotli 6.0.0", - "bytes", - "cache_control", - "deno_core", - "deno_net", - "deno_websocket", - "flate2", - "http 0.2.12", - "http 1.1.0", - "httparse", - "hyper 0.14.31", - "hyper 1.6.0", - "hyper-util", - "itertools 0.10.5", - "memmem", - "mime", - "once_cell", - "percent-encoding", - "phf", - "pin-project", - "ring 0.17.8", - "scopeguard", - "serde", - "smallvec", - "thiserror 1.0.69", - "tokio", - "tokio-util 0.7.12", -] - -[[package]] -name = "deno_io" -version = "0.90.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "async-trait", - "deno_core", - "filetime", - "fs3", - "libc", - "log", - "once_cell", - "os_pipe", - "parking_lot 0.12.3", - "pin-project", - "rand 0.8.5", - "tokio", - "uuid", - "winapi", - "windows-sys 0.52.0", -] - -[[package]] -name = "deno_kv" -version = "0.88.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "anyhow", - "async-trait", - "base64 0.21.7", - "boxed_error", - "bytes", - "chrono", - "deno_core", - "deno_fetch", - "deno_path_util", - "deno_permissions", - "deno_tls", - "denokv_proto", - "denokv_remote", - "denokv_sqlite", - "faster-hex", - "http 1.1.0", - "http-body-util", - "log", - "num-bigint", - "prost 0.13.4", - "prost-build 0.13.4", - "rand 0.8.5", - "rusqlite", - "serde", - "thiserror 1.0.69", - "url", -] - -[[package]] -name = "deno_media_type" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8978229b82552bf8457a0125aa20863f023619cfc21ebb007b1e571d68fd85b" -dependencies = [ - "data-url", - "serde", - "url", -] - -[[package]] -name = "deno_media_type" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaa135b8a9febc9a51c16258e294e268a1276750780d69e46edb31cced2826e4" -dependencies = [ - "data-url", - "serde", - "url", -] - -[[package]] -name = "deno_napi" -version = "0.111.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "deno_core", - "deno_permissions", - "libc", - "libloading 0.7.4", - "log", - "napi_sym", - "thiserror 1.0.69", - "windows-sys 0.52.0", -] - -[[package]] -name = "deno_native_certs" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86bc737e098a45aa5742d51ce694ac7236a1e69fb0d9df8c862e9b4c9583c5f9" -dependencies = [ - "dlopen2 0.7.0", - "dlopen2_derive", - "once_cell", - "rustls-native-certs 0.7.3", - "rustls-pemfile 2.2.0", -] - -[[package]] -name = "deno_net" -version = "0.172.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "deno_core", - "deno_permissions", - "deno_tls", - "hickory-proto", - "hickory-resolver", - "pin-project", - "rustls-tokio-stream", - "serde", - "socket2 0.5.8", - "thiserror 1.0.69", - "tokio", -] - -[[package]] -name = "deno_node" -version = "0.117.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "aead-gcm-stream", - "aes", - "async-trait", - "base64 0.21.7", - "blake2", - "boxed_error", - "brotli 6.0.0", - "bytes", - "cbc", - "const-oid", - "data-encoding", - "deno_core", - "deno_fetch", - "deno_fs", - "deno_io", - "deno_media_type 0.2.2", - "deno_net", - "deno_package_json", - "deno_path_util", - "deno_permissions", - "deno_whoami", - "der 0.7.9", - "digest 0.10.7", - "dsa", - "ecb", - "ecdsa 0.16.9", - "ed25519-dalek", - "elliptic-curve 0.13.8", - "errno 0.2.8", - "faster-hex", - "h2 0.4.7", - "hkdf", - "home", - "http 1.1.0", - "http-body-util", - "hyper 1.6.0", - "hyper-util", - "idna 1.0.3", - "indexmap 2.7.0", - "ipnetwork", - "k256", - "lazy-regex", - "libc", - "libz-sys", - "md-5", - "md4", - "memchr", - "node_resolver", - "num-bigint", - "num-bigint-dig", - "num-integer", - "num-traits", - "once_cell", - "p224", - "p256 0.13.2", - "p384", - "path-clean", - "pbkdf2", - "pin-project-lite", - "pkcs8 0.10.2", - "rand 0.8.5", - "regex", - "ring 0.17.8", - "ripemd", - "rsa", - "scrypt", - "sec1 0.7.3", - "serde", - "sha1", - "sha2 0.10.8", - "sha3", - "signature 2.2.0", - "simd-json", - "sm3", - "spki 0.7.3", - "stable_deref_trait", - "thiserror 1.0.69", - "tokio", - "tokio-eld", - "url", - "webpki-root-certs", - "winapi", - "windows-sys 0.52.0", - "x25519-dalek", - "x509-parser", - "yoke", -] - -[[package]] -name = "deno_ops" -version = "0.199.0" -source = "git+https://github.com/rivet-gg/deno_core?rev=8a313913fa73d58f4f9532565b0084e723bc34ad#8a313913fa73d58f4f9532565b0084e723bc34ad" -dependencies = [ - "proc-macro-rules", - "proc-macro2", - "quote", - "stringcase", - "strum 0.25.0", - "strum_macros 0.25.3", - "syn 2.0.90", - "thiserror 1.0.69", -] - -[[package]] -name = "deno_package_json" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80b0a3d81c592624a1ae15332a04b4dc2b7c163ef1dfc7c60171f736d1babdf5" -dependencies = [ - "deno_error", - "deno_path_util", - "deno_semver", - "indexmap 2.7.0", - "serde", - "serde_json", - "thiserror 2.0.12", - "url", -] - -[[package]] -name = "deno_path_util" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff25f6e08e7a0214bbacdd6f7195c7f1ebcd850c87a624e4ff06326b68b42d99" -dependencies = [ - "percent-encoding", - "thiserror 1.0.69", - "url", -] - -[[package]] -name = "deno_permissions" -version = "0.40.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "deno_core", - "deno_path_util", - "deno_terminal 0.2.0", - "fqdn", - "libc", - "log", - "once_cell", - "percent-encoding", - "serde", - "thiserror 1.0.69", - "which 4.4.2", - "winapi", -] - -[[package]] -name = "deno_runtime" -version = "0.189.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "color-print", - "deno_ast 0.44.0", - "deno_broadcast_channel", - "deno_cache", - "deno_canvas", - "deno_console", - "deno_core", - "deno_cron", - "deno_crypto", - "deno_fetch", - "deno_ffi", - "deno_fs", - "deno_http", - "deno_io", - "deno_kv", - "deno_napi", - "deno_net", - "deno_node", - "deno_path_util", - "deno_permissions", - "deno_telemetry", - "deno_terminal 0.2.0", - "deno_tls", - "deno_url", - "deno_web", - "deno_webgpu", - "deno_webidl", - "deno_websocket", - "deno_webstorage", - "dlopen2 0.6.1", - "encoding_rs", - "fastwebsockets", - "flate2", - "http 1.1.0", - "http-body-util", - "hyper 0.14.31", - "hyper 1.6.0", - "hyper-util", - "libc", - "log", - "netif", - "nix 0.27.1", - "node_resolver", - "notify", - "ntapi", - "once_cell", - "percent-encoding", - "regex", - "rustyline 13.0.0", - "same-file", - "serde", - "signal-hook", - "signal-hook-registry", - "tempfile", - "thiserror 1.0.69", - "tokio", - "tokio-metrics", - "twox-hash", - "uuid", - "which 4.4.2", - "winapi", - "windows-sys 0.52.0", -] - -[[package]] -name = "deno_semver" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d1259270d66a5e6d29bb75c9289656541874f79ae9ff6c9f1c790846d5c07ba" -dependencies = [ - "deno_error", - "monch", - "once_cell", - "serde", - "thiserror 2.0.12", - "url", -] - -[[package]] -name = "deno_telemetry" -version = "0.2.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "async-trait", - "deno_core", - "http-body-util", - "hyper 1.6.0", - "hyper-util", - "log", - "once_cell", - "opentelemetry 0.27.1", - "opentelemetry-http 0.27.0", - "opentelemetry-otlp 0.27.0", - "opentelemetry-semantic-conventions 0.27.0", - "opentelemetry_sdk 0.27.1", - "pin-project", - "serde", - "tokio", -] - -[[package]] -name = "deno_terminal" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e6337d4e7f375f8b986409a76fbeecfa4bd8a1343e63355729ae4befa058eaf" -dependencies = [ - "once_cell", - "termcolor", -] - -[[package]] -name = "deno_terminal" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daef12499e89ee99e51ad6000a91f600d3937fb028ad4918af76810c5bc9e0d5" -dependencies = [ - "once_cell", - "termcolor", -] - -[[package]] -name = "deno_tls" -version = "0.167.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "deno_core", - "deno_native_certs", - "rustls 0.23.25", - "rustls-pemfile 2.2.0", - "rustls-tokio-stream", - "rustls-webpki 0.102.8", - "serde", - "thiserror 1.0.69", - "tokio", - "webpki-roots 0.26.7", -] - -[[package]] -name = "deno_unsync" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d774fd83f26b24f0805a6ab8b26834a0d06ceac0db517b769b1e4633c96a2057" -dependencies = [ - "futures", - "parking_lot 0.12.3", - "tokio", -] - -[[package]] -name = "deno_url" -version = "0.180.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "deno_core", - "thiserror 1.0.69", - "urlpattern", -] - -[[package]] -name = "deno_web" -version = "0.211.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "async-trait", - "base64-simd 0.8.0", - "bytes", - "deno_core", - "deno_permissions", - "encoding_rs", - "flate2", - "futures", - "serde", - "thiserror 1.0.69", - "tokio", - "uuid", -] - -[[package]] -name = "deno_webgpu" -version = "0.147.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "deno_core", - "raw-window-handle", - "serde", - "thiserror 1.0.69", - "tokio", - "wgpu-core", - "wgpu-types", -] - -[[package]] -name = "deno_webidl" -version = "0.180.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "deno_core", -] - -[[package]] -name = "deno_websocket" -version = "0.185.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "bytes", - "deno_core", - "deno_net", - "deno_permissions", - "deno_tls", - "fastwebsockets", - "h2 0.4.7", - "http 1.1.0", - "http-body-util", - "hyper 1.6.0", - "hyper-util", - "once_cell", - "rustls-tokio-stream", - "serde", - "thiserror 1.0.69", - "tokio", -] - -[[package]] -name = "deno_webstorage" -version = "0.175.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "deno_core", - "deno_web", - "rusqlite", - "thiserror 1.0.69", -] - -[[package]] -name = "deno_whoami" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e75e4caa92b98a27f09c671d1399aee0f5970aa491b9a598523aac000a2192e3" -dependencies = [ - "libc", - "whoami", -] - -[[package]] -name = "denokv_proto" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7ba1f99ed11a9c11e868a8521b1f71a7e1aba785d7f42ea9ecbdc01146c89ec" -dependencies = [ - "anyhow", - "async-trait", - "chrono", - "futures", - "num-bigint", - "prost 0.13.4", - "serde", - "uuid", -] - -[[package]] -name = "denokv_remote" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08ed833073189e8f6d03155fe3b05a024e75e29d8a28a4c2e9ec3b5c925e727b" -dependencies = [ - "anyhow", - "async-stream", - "async-trait", - "bytes", - "chrono", - "denokv_proto", - "futures", - "http 1.1.0", - "log", - "prost 0.13.4", - "rand 0.8.5", - "serde", - "serde_json", - "tokio", - "tokio-util 0.7.12", - "url", - "uuid", -] - -[[package]] -name = "denokv_sqlite" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b790f01d1302d53a0c3cbd27de88a06b3abd64ec8ab8673924e490541c7c713" -dependencies = [ - "anyhow", - "async-stream", - "async-trait", - "chrono", - "denokv_proto", - "futures", - "hex", - "log", - "num-bigint", - "rand 0.8.5", - "rusqlite", - "serde_json", - "thiserror 1.0.69", - "tokio", - "tokio-stream", - "uuid", - "v8_valueserializer", -] - -[[package]] -name = "der" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" -dependencies = [ - "const-oid", - "zeroize", -] - -[[package]] -name = "der" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" -dependencies = [ - "const-oid", - "der_derive", - "pem-rfc7468", - "zeroize", -] - -[[package]] -name = "der-parser" -version = "8.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" -dependencies = [ - "asn1-rs", - "displaydoc", - "nom 7.1.3", - "num-bigint", - "num-traits", - "rusticata-macros", -] - -[[package]] -name = "der_derive" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", - "serde", -] - -[[package]] -name = "derive_builder" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" -dependencies = [ - "derive_builder_macro 0.12.0", -] - -[[package]] -name = "derive_builder" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" -dependencies = [ - "derive_builder_macro 0.20.2", -] - -[[package]] -name = "derive_builder_core" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" -dependencies = [ - "darling 0.14.4", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "derive_builder_core" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" -dependencies = [ - "darling 0.20.10", - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "derive_builder_macro" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" -dependencies = [ - "derive_builder_core 0.12.0", - "syn 1.0.109", -] - -[[package]] -name = "derive_builder_macro" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" -dependencies = [ - "derive_builder_core 0.20.2", - "syn 2.0.90", -] - -[[package]] -name = "difflib" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer 0.10.4", - "const-oid", - "crypto-common", - "subtle", -] - -[[package]] -name = "dirs" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.48.0", -] - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "divan" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0583193020b29b03682d8d33bb53a5b0f50df6daacece12ca99b904cfdcb8c4" -dependencies = [ - "cfg-if", - "clap", - "condtype", - "divan-macros", - "libc", - "regex-lite", -] - -[[package]] -name = "divan-macros" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dc51d98e636f5e3b0759a39257458b22619cac7e96d932da6eeb052891bb67c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "dlopen2" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bc2c7ed06fd72a8513ded8d0d2f6fd2655a85d6885c48cae8625d80faf28c03" -dependencies = [ - "dlopen2_derive", - "libc", - "once_cell", - "winapi", -] - -[[package]] -name = "dlopen2" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1297103d2bbaea85724fcee6294c2d50b1081f9ad47d0f6f6f61eda65315a6" -dependencies = [ - "dlopen2_derive", - "libc", - "once_cell", - "winapi", -] - -[[package]] -name = "dlopen2_derive" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "doc-comment" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" - -[[package]] -name = "docker_credential" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d89dfcba45b4afad7450a99b39e751590463e45c04728cf555d36bb66940de8" -dependencies = [ - "base64 0.21.7", - "serde", - "serde_json", -] - -[[package]] -name = "document-features" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" -dependencies = [ - "litrs", -] - -[[package]] -name = "dotenvy" -version = "0.15.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" - -[[package]] -name = "dprint-swc-ext" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ba28c12892aadb751c2ba7001d8460faee4748a04b4edc51c7121cc67ee03db" -dependencies = [ - "num-bigint", - "rustc-hash 1.1.0", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_parser", - "text_lines", -] - -[[package]] -name = "dsa" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48bc224a9084ad760195584ce5abb3c2c34a225fa312a128ad245a6b412b7689" -dependencies = [ - "digest 0.10.7", - "num-bigint-dig", - "num-traits", - "pkcs8 0.10.2", - "rfc6979 0.4.0", - "sha2 0.10.8", - "signature 2.2.0", - "zeroize", -] - -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - -[[package]] -name = "dyn-clone" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" - -[[package]] -name = "dynamic-config" -version = "25.5.2" -dependencies = [ - "chirp-workflow", - "indoc 2.0.5", - "rivet-config", - "rivet-operation", - "tokio", -] - -[[package]] -name = "dynasm" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add9a102807b524ec050363f09e06f1504214b0e1c7797f64261c891022dce8b" -dependencies = [ - "bitflags 1.3.2", - "byteorder", - "lazy_static", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "dynasmrt" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64fba5a42bd76a17cad4bfa00de168ee1cbfa06a5e8ce992ae880218c05641a9" -dependencies = [ - "byteorder", - "dynasm", - "memmap2", -] - -[[package]] -name = "ecb" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a8bfa975b1aec2145850fcaa1c6fe269a16578c44705a532ae3edc92b8881c7" -dependencies = [ - "cipher", -] - -[[package]] -name = "ecdsa" -version = "0.14.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" -dependencies = [ - "der 0.6.1", - "elliptic-curve 0.12.3", - "rfc6979 0.3.1", - "signature 1.6.4", -] - -[[package]] -name = "ecdsa" -version = "0.16.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" -dependencies = [ - "der 0.7.9", - "digest 0.10.7", - "elliptic-curve 0.13.8", - "rfc6979 0.4.0", - "signature 2.2.0", - "spki 0.7.3", -] - -[[package]] -name = "ed25519" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" -dependencies = [ - "pkcs8 0.10.2", - "signature 2.2.0", -] - -[[package]] -name = "ed25519-dalek" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" -dependencies = [ - "curve25519-dalek", - "ed25519", - "rand_core 0.6.4", - "serde", - "sha2 0.10.8", - "signature 2.2.0", - "subtle", - "zeroize", -] - -[[package]] -name = "ed448-goldilocks" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06924531e9e90130842b012e447f85bdaf9161bc8a0f8092be8cb70b01ebe092" -dependencies = [ - "fiat-crypto 0.1.20", - "hex", - "subtle", - "zeroize", -] - -[[package]] -name = "edge-monolith-workflow-worker" -version = "25.5.2" -dependencies = [ - "chirp-workflow", - "pegboard", - "rivet-config", - "rivet-health-checks", - "rivet-metrics", - "rivet-runtime", -] - -[[package]] -name = "either" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" -dependencies = [ - "serde", -] - -[[package]] -name = "elliptic-curve" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" -dependencies = [ - "base16ct 0.1.1", - "crypto-bigint 0.4.9", - "der 0.6.1", - "digest 0.10.7", - "ff 0.12.1", - "generic-array", - "group 0.12.1", - "pkcs8 0.9.0", - "rand_core 0.6.4", - "sec1 0.3.0", - "subtle", - "zeroize", -] - -[[package]] -name = "elliptic-curve" -version = "0.13.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct 0.2.0", - "base64ct", - "crypto-bigint 0.5.5", - "digest 0.10.7", - "ff 0.13.0", - "generic-array", - "group 0.13.0", - "hkdf", - "pem-rfc7468", - "pkcs8 0.10.2", - "rand_core 0.6.4", - "sec1 0.7.3", - "serde_json", - "serdect", - "subtle", - "zeroize", -] - -[[package]] -name = "email-address-parser" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1840503695adadbe314fe6cedd297fbc406d13f0fe06fd28d02e499a17c2a599" -dependencies = [ - "console_error_panic_hook", - "pest", - "pest_derive", - "quick-xml", - "wasm-bindgen", -] - -[[package]] -name = "email-send" -version = "25.5.2" -dependencies = [ - "base64 0.13.1", - "chirp-client", - "chirp-worker", - "lazy_static", - "prost 0.10.4", - "reqwest 0.12.12", - "rivet-operation", - "serde", - "serde_json", -] - -[[package]] -name = "email-verification-complete" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "debug-email-res", - "email-verification-create", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "email-verification-create" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "email-address-parser", - "email-send", - "faker-game", - "game-get", - "game-logo-upload-complete", - "prost 0.10.4", - "rand 0.8.5", - "reqwest 0.11.27", - "rivet-operation", - "serde_json", - "sqlx", - "upload-prepare", -] - -[[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - -[[package]] -name = "encoding_rs" -version = "0.8.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "endian-type" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" - -[[package]] -name = "enum-as-inner" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "envy" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f47e0157f2cb54f5ae1bd371b30a2ae4311e1c028f575cd4e81de7353215965" -dependencies = [ - "serde", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" -dependencies = [ - "errno-dragonfly", - "libc", - "winapi", -] - -[[package]] -name = "errno" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "error-code" -version = "3.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f" - -[[package]] -name = "error_reporter" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31ae425815400e5ed474178a7a22e275a9687086a12ca63ec793ff292d8fdae8" - -[[package]] -name = "etcetera" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" -dependencies = [ - "cfg-if", - "home", - "windows-sys 0.48.0", -] - -[[package]] -name = "etcetera" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c7b13d0780cb82722fd59f6f57f925e143427e4a75313a6c77243bf5326ae6" -dependencies = [ - "cfg-if", - "home", - "windows-sys 0.59.0", -] - -[[package]] -name = "event-listener" -version = "5.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" -dependencies = [ - "event-listener", - "pin-project-lite", -] - -[[package]] -name = "external-request-validate" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "http 0.2.12", - "prost 0.10.4", - "reqwest 0.12.12", - "rivet-operation", - "serde", - "serde_json", - "sqlx", -] - -[[package]] -name = "external-worker" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "reqwest 0.12.12", - "rivet-config", - "rivet-health-checks", - "rivet-metrics", - "rivet-runtime", -] - -[[package]] -name = "faker-build" -version = "25.5.2" -dependencies = [ - "build-create", - "chirp-client", - "chirp-worker", - "faker-game", - "prost 0.10.4", - "rivet-operation", - "uuid", -] - -[[package]] -name = "faker-cdn-site" -version = "25.5.2" -dependencies = [ - "cdn-site-create", - "chirp-client", - "chirp-worker", - "faker-game", - "prost 0.10.4", - "reqwest 0.11.27", - "rivet-operation", - "upload-complete", -] - -[[package]] -name = "faker-game" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "cloud-game-config-create", - "faker-game-namespace", - "faker-game-version", - "faker-team", - "game-create", - "game-get", - "mm-config-game-upsert", - "prost 0.10.4", - "rivet-operation", -] - -[[package]] -name = "faker-game-namespace" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "cloud-namespace-create", - "faker-game", - "game-namespace-create", - "prost 0.10.4", - "rivet-operation", -] - -[[package]] -name = "faker-game-version" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "cloud-version-publish", - "faker-build", - "faker-cdn-site", - "faker-game", - "faker-region", - "game-namespace-version-set", - "mm-config-version-get", - "prost 0.10.4", - "region-list", - "rivet-operation", - "rivet-util-mm", -] - -[[package]] -name = "faker-job-run" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-job-template", - "faker-region", - "job-run", - "prost 0.10.4", - "rivet-operation", - "rivet-test", -] - -[[package]] -name = "faker-job-template" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "nomad-client", - "prost 0.10.4", - "rivet-operation", - "rivet-util-job", -] - -[[package]] -name = "faker-mm-lobby" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-build", - "faker-game", - "faker-game-version", - "faker-region", - "game-namespace-version-set", - "game-resolve-namespace-id", - "mm-config-version-get", - "prost 0.10.4", - "rivet-operation", - "rivet-test", - "rivet-util-mm", -] - -[[package]] -name = "faker-mm-lobby-row" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "prost 0.10.4", - "rivet-operation", - "rivet-util-mm", -] - -[[package]] -name = "faker-mm-player" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "token-create", -] - -[[package]] -name = "faker-region" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "region-get", - "region-list", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "faker-team" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-user", - "prost 0.10.4", - "rivet-operation", - "team-get", -] - -[[package]] -name = "faker-user" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "user-get", -] - -[[package]] -name = "fallible-iterator" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" - -[[package]] -name = "fallible-streaming-iterator" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" - -[[package]] -name = "faster-hex" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183" -dependencies = [ - "serde", -] - -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[package]] -name = "fastrand" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" - -[[package]] -name = "fastwebsockets" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26da0c7b5cef45c521a6f9cdfffdfeb6c9f5804fbac332deb5ae254634c7a6be" -dependencies = [ - "base64 0.21.7", - "bytes", - "http-body-util", - "hyper 1.6.0", - "hyper-util", - "pin-project", - "rand 0.8.5", - "sha1", - "simdutf8", - "thiserror 1.0.69", - "tokio", - "utf-8", -] - -[[package]] -name = "fd-lock" -version = "4.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e5768da2206272c81ef0b5e951a41862938a6070da63bcea197899942d3b947" -dependencies = [ - "cfg-if", - "rustix", - "windows-sys 0.52.0", -] - -[[package]] -name = "fdb-util" -version = "25.5.2" -dependencies = [ - "anyhow", - "foundationdb", - "lazy_static", - "rivet-metrics", - "tokio", - "tracing", -] - -[[package]] -name = "fdeflate" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "ff" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "ff" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "fiat-crypto" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" - -[[package]] -name = "fiat-crypto" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" - -[[package]] -name = "filetime" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" -dependencies = [ - "cfg-if", - "libc", - "libredox", - "windows-sys 0.59.0", -] - -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - -[[package]] -name = "flate2" -version = "1.0.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" -dependencies = [ - "crc32fast", - "miniz_oxide 0.8.0", -] - -[[package]] -name = "float-cmp" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8" -dependencies = [ - "num-traits", -] - -[[package]] -name = "flume" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" -dependencies = [ - "futures-core", - "futures-sink", - "spin 0.9.8", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foldhash" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared 0.1.1", -] - -[[package]] -name = "foreign-types" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" -dependencies = [ - "foreign-types-macros", - "foreign-types-shared 0.3.1", -] - -[[package]] -name = "foreign-types-macros" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "foreign-types-shared" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "formatted-error" -version = "25.5.2" -dependencies = [ - "gray_matter", - "hashbrown 0.12.3", - "http 0.2.12", - "indoc 1.0.9", - "lazy_static", - "serde", -] - -[[package]] -name = "foundationdb" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c30b4254cb4c01b50a74dad6aa48e17666726300b3adddb3c959a7e852f286bd" -dependencies = [ - "async-recursion", - "async-trait", - "foundationdb-gen", - "foundationdb-macros", - "foundationdb-sys", - "futures", - "memchr", - "rand 0.8.5", - "serde", - "serde_bytes", - "serde_json", - "static_assertions", - "uuid", -] - -[[package]] -name = "foundationdb-gen" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93b9deedf92107a1076e518d60931b6ed1a632ae0c51e7b491bfd42edb4148ce" -dependencies = [ - "xml-rs", -] - -[[package]] -name = "foundationdb-macros" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc84a5ff0dba78222551017f5625f3365aa09551c78cfaa44136fc6818c2611" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", - "try_map", -] - -[[package]] -name = "foundationdb-sys" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bae14dba30b8dcc4905a9189ebb18bc9db9744ef0ad8f2b94ef00d21e176964" -dependencies = [ - "bindgen 0.70.1", - "libc", -] - -[[package]] -name = "fqdn" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb540cf7bc4fe6df9d8f7f0c974cfd0dce8ed4e9e8884e73433b503ee78b4e7d" - -[[package]] -name = "from_variant" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32016f1242eb82af5474752d00fd8ebcd9004bd69b462b1c91de833972d08ed4" -dependencies = [ - "proc-macro2", - "swc_macros_common", - "syn 2.0.90", -] - -[[package]] -name = "fs3" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb17cf6ed704f72485332f6ab65257460c4f9f3083934cf402bf9f5b3b600a90" -dependencies = [ - "libc", - "rustc_version 0.2.3", - "winapi", -] - -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - -[[package]] -name = "fsevent-sys" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" -dependencies = [ - "libc", -] - -[[package]] -name = "fslock" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04412b8935272e3a9bae6f48c7bfff74c2911f60525404edfdd28e49884c3bfb" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "funty" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "futures" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-executor" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-intrusive" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" -dependencies = [ - "futures-core", - "lock_api", - "parking_lot 0.12.3", -] - -[[package]] -name = "futures-io" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" - -[[package]] -name = "futures-macro" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "futures-sink" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" - -[[package]] -name = "futures-task" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" - -[[package]] -name = "futures-timer" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" - -[[package]] -name = "futures-util" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "fuzzy-matcher" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94" -dependencies = [ - "thread_local", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] -name = "game-banner-upload-complete" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "prost 0.10.4", - "reqwest 0.11.27", - "rivet-operation", - "sqlx", - "upload-complete", - "upload-get", - "upload-prepare", -] - -[[package]] -name = "game-create" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chirp-workflow", - "cluster", - "faker-team", - "game-validate", - "prost 0.10.4", - "rivet-operation", - "rivet-util-team", - "sqlx", - "team-get", -] - -[[package]] -name = "game-get" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-team", - "game-create", - "prost 0.10.4", - "rivet-operation", - "sqlx", - "upload-file-list", - "upload-get", -] - -[[package]] -name = "game-list-all" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "game-list-for-team" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "faker-team", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "game-logo-upload-complete" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "prost 0.10.4", - "reqwest 0.11.27", - "rivet-operation", - "sqlx", - "upload-complete", - "upload-get", - "upload-prepare", -] - -[[package]] -name = "game-namespace-create" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "game-namespace-validate", - "game-version-create", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "game-namespace-get" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "game-namespace-create", - "game-version-create", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "game-namespace-list" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "game-namespace-create", - "game-version-create", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "game-namespace-resolve-name-id" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "faker-game-namespace", - "game-namespace-get", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "game-namespace-resolve-url" -version = "25.5.2" -dependencies = [ - "cdn-namespace-domain-create", - "cdn-namespace-resolve-domain", - "chirp-client", - "chirp-worker", - "faker-game", - "game-get", - "game-namespace-get", - "game-namespace-list", - "game-namespace-resolve-name-id", - "game-resolve-name-id", - "prost 0.10.4", - "rivet-operation", - "url", -] - -[[package]] -name = "game-namespace-validate" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "game-namespace-resolve-name-id", - "prost 0.10.4", - "rivet-operation", -] - -[[package]] -name = "game-namespace-version-history-list" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "game-namespace-version-set" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "game-get", - "game-resolve-namespace-id", - "game-version-create", - "mm-lobby-idle-update", - "prost 0.10.4", - "region-list-for-game", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "game-recommend" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "game-resolve-name-id" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "game-get", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "game-resolve-namespace-id" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "game-namespace-create", - "game-version-create", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "game-token-development-validate" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", -] - -[[package]] -name = "game-validate" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "game-resolve-name-id", - "prost 0.10.4", - "rivet-operation", -] - -[[package]] -name = "game-version-create" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "game-version-get", - "game-version-list", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "game-version-get" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "game-version-create", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "game-version-list" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "game-version-create", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "game-version-validate" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chirp-workflow", - "external-request-validate", - "faker-game", - "game-version-get", - "game-version-list", - "mm-config-game-get", - "prost 0.10.4", - "region-get", - "rivet-operation", - "rivet-util-mm", - "tier", -] - -[[package]] -name = "generator" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6bd114ceda131d3b1d665eba35788690ad37f5916457286b32ab6fd3c438dd" -dependencies = [ - "cfg-if", - "libc", - "log", - "rustversion", - "windows 0.58.0", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", - "zeroize", -] - -[[package]] -name = "geoutils" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e006f616a407d396ace1d2ebb3f43ed73189db8b098079bd129928d7645dd1e" - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasi 0.14.2+wasi-0.2.4", -] - -[[package]] -name = "ghash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" -dependencies = [ - "opaque-debug", - "polyval", -] - -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - -[[package]] -name = "gl_generator" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" -dependencies = [ - "khronos_api", - "log", - "xml-rs", -] - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "global-error" -version = "25.5.2" -dependencies = [ - "async-trait", - "formatted-error", - "http 0.2.12", - "reqwest 0.12.12", - "serde", - "serde_json", - "thiserror 1.0.69", - "types-proto", -] - -[[package]] -name = "globset" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" -dependencies = [ - "aho-corasick", - "bstr", - "log", - "regex-automata 0.4.9", - "regex-syntax 0.8.5", -] - -[[package]] -name = "glow" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd348e04c43b32574f2de31c8bb397d96c9fcfa1371bd4ca6d8bdc464ab121b1" -dependencies = [ - "js-sys", - "slotmap", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "glutin_wgl_sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8098adac955faa2d31079b65dc48841251f69efd3ac25477903fc424362ead" -dependencies = [ - "gl_generator", -] - -[[package]] -name = "governor" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a7f542ee6b35af73b06abc0dad1c1bae89964e4e253bc4b587b91c9637867b" -dependencies = [ - "cfg-if", - "dashmap", - "futures", - "futures-timer", - "no-std-compat", - "nonzero_ext", - "parking_lot 0.12.3", - "portable-atomic", - "quanta", - "rand 0.8.5", - "smallvec", - "spinning_top", -] - -[[package]] -name = "gpu-alloc" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" -dependencies = [ - "bitflags 2.6.0", - "gpu-alloc-types", -] - -[[package]] -name = "gpu-alloc-types" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" -dependencies = [ - "bitflags 2.6.0", -] - -[[package]] -name = "gpu-descriptor" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf29e94d6d243368b7a56caa16bc213e4f9f8ed38c4d9557069527b5d5281ca" -dependencies = [ - "bitflags 2.6.0", - "gpu-descriptor-types", - "hashbrown 0.15.2", -] - -[[package]] -name = "gpu-descriptor-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" -dependencies = [ - "bitflags 2.6.0", -] - -[[package]] -name = "gray_matter" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31ee6a6070bad7c953b0c8be9367e9372181fed69f3e026c4eb5160d8b3c0222" -dependencies = [ - "serde", - "serde_json", - "toml 0.5.11", - "yaml-rust2", -] - -[[package]] -name = "group" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" -dependencies = [ - "ff 0.12.1", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff 0.13.0", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "gzip-header" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95cc527b92e6029a62960ad99aa8a6660faa4555fe5f731aab13aa6a921795a2" -dependencies = [ - "crc32fast", -] - -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap 2.7.0", - "slab", - "tokio", - "tokio-util 0.7.12", - "tracing", -] - -[[package]] -name = "h2" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http 1.1.0", - "indexmap 2.7.0", - "slab", - "tokio", - "tokio-util 0.7.12", - "tracing", -] - -[[package]] -name = "halfbrown" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8588661a8607108a5ca69cab034063441a0413a0b041c13618a7dd348021ef6f" -dependencies = [ - "hashbrown 0.14.5", - "serde", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.8", -] - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash 0.8.11", - "allocator-api2", -] - -[[package]] -name = "hashbrown" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash", -] - -[[package]] -name = "hashlink" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" -dependencies = [ - "hashbrown 0.14.5", -] - -[[package]] -name = "hashlink" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" -dependencies = [ - "hashbrown 0.14.5", -] - -[[package]] -name = "hdrhistogram" -version = "7.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d" -dependencies = [ - "base64 0.21.7", - "byteorder", - "crossbeam-channel", - "flate2", - "nom 7.1.3", - "num-traits", -] - -[[package]] -name = "headers" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" -dependencies = [ - "base64 0.21.7", - "bytes", - "headers-core", - "http 0.2.12", - "httpdate", - "mime", - "sha1", -] - -[[package]] -name = "headers-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" -dependencies = [ - "http 0.2.12", -] - -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hexf-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" - -[[package]] -name = "hickory-proto" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447afdcdb8afb9d0a852af6dc65d9b285ce720ed7a59e42a8bf2e931c67bc1b5" -dependencies = [ - "async-trait", - "cfg-if", - "data-encoding", - "enum-as-inner", - "futures-channel", - "futures-io", - "futures-util", - "idna 1.0.3", - "ipnet", - "once_cell", - "rand 0.8.5", - "serde", - "thiserror 1.0.69", - "tinyvec", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "hickory-resolver" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a2e2aba9c389ce5267d31cf1e4dace82390ae276b0b364ea55630b1fa1b44b4" -dependencies = [ - "cfg-if", - "futures-util", - "hickory-proto", - "ipconfig", - "lru-cache", - "once_cell", - "parking_lot 0.12.3", - "rand 0.8.5", - "resolv-conf", - "serde", - "smallvec", - "thiserror 1.0.69", - "tokio", - "tracing", -] - -[[package]] -name = "hkdf" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" -dependencies = [ - "hmac 0.12.1", -] - -[[package]] -name = "hmac" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" -dependencies = [ - "crypto-mac", - "digest 0.9.0", -] - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "hostname" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" -dependencies = [ - "libc", - "match_cfg", - "winapi", -] - -[[package]] -name = "hstr" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dae404c0c5d4e95d4858876ab02eecd6a196bb8caa42050dfa809938833fc412" -dependencies = [ - "hashbrown 0.14.5", - "new_debug_unreachable", - "once_cell", - "phf", - "rustc-hash 1.1.0", - "triomphe", -] - -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa 1.0.14", -] - -[[package]] -name = "http" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" -dependencies = [ - "bytes", - "fnv", - "itoa 1.0.14", -] - -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http 1.1.0", -] - -[[package]] -name = "http-body-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" -dependencies = [ - "bytes", - "futures-util", - "http 1.1.0", - "http-body 1.0.1", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "humansize" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026" - -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - -[[package]] -name = "hyper" -version = "0.14.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa 1.0.14", - "pin-project-lite", - "socket2 0.5.8", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "h2 0.4.7", - "http 1.1.0", - "http-body 1.0.1", - "httparse", - "httpdate", - "itoa 1.0.14", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-named-pipe" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b7d8abf35697b81a825e386fc151e0d503e8cb5fcb93cc8669c376dfd6f278" -dependencies = [ - "hex", - "hyper 1.6.0", - "hyper-util", - "pin-project-lite", - "tokio", - "tower-service", - "winapi", -] - -[[package]] -name = "hyper-rustls" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64" -dependencies = [ - "ct-logs", - "futures-util", - "hyper 0.14.31", - "log", - "rustls 0.19.1", - "rustls-native-certs 0.5.0", - "tokio", - "tokio-rustls 0.22.0", - "webpki 0.21.4", -] - -[[package]] -name = "hyper-rustls" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http 0.2.12", - "hyper 0.14.31", - "log", - "rustls 0.21.12", - "rustls-native-certs 0.6.3", - "tokio", - "tokio-rustls 0.24.1", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" -dependencies = [ - "futures-util", - "http 1.1.0", - "hyper 1.6.0", - "hyper-util", - "rustls 0.23.25", - "rustls-pki-types", - "tokio", - "tokio-rustls 0.26.2", - "tower-service", - "webpki-roots 0.26.7", -] - -[[package]] -name = "hyper-timeout" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" -dependencies = [ - "hyper 1.6.0", - "hyper-util", - "pin-project-lite", - "tokio", - "tower-service", -] - -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper 0.14.31", - "native-tls", - "tokio", - "tokio-native-tls", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper 1.6.0", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - -[[package]] -name = "hyper-tungstenite" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0110a0487cbc65c3d1f38c2ef851dbf8bee8c2761e5a96be6a59ba84412b4752" -dependencies = [ - "http-body-util", - "hyper 1.6.0", - "hyper-util", - "pin-project-lite", - "tokio", - "tokio-tungstenite 0.26.2", - "tungstenite 0.26.2", -] - -[[package]] -name = "hyper-util" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http 1.1.0", - "http-body 1.0.1", - "hyper 1.6.0", - "pin-project-lite", - "socket2 0.5.8", - "tokio", - "tower-service", - "tracing", -] - -[[package]] -name = "hyperlocal" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "986c5ce3b994526b3cd75578e62554abd09f0899d6206de48b3e96ab34ccc8c7" -dependencies = [ - "hex", - "http-body-util", - "hyper 1.6.0", - "hyper-util", - "pin-project-lite", - "tokio", - "tower-service", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core 0.52.0", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "icu_collections" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locid" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - -[[package]] -name = "icu_normalizer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "utf16_iter", - "utf8_iter", - "write16", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" - -[[package]] -name = "icu_properties" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locid_transform", - "icu_properties_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" - -[[package]] -name = "icu_provider" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_provider_macros", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "idna" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - -[[package]] -name = "if_chain" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" - -[[package]] -name = "ignore" -version = "0.4.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" -dependencies = [ - "crossbeam-deque", - "globset", - "log", - "memchr", - "regex-automata 0.4.9", - "same-file", - "walkdir", - "winapi-util", -] - -[[package]] -name = "image" -version = "0.24.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "num-traits", - "png", -] - -[[package]] -name = "include_dir" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd" -dependencies = [ - "include_dir_macros", -] - -[[package]] -name = "include_dir_macros" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", -] - -[[package]] -name = "indexmap" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" -dependencies = [ - "equivalent", - "hashbrown 0.15.2", - "serde", -] - -[[package]] -name = "indicatif" -version = "0.17.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf675b85ed934d3c67b5c5469701eec7db22689d0a2139d856e0925fa28b281" -dependencies = [ - "console", - "number_prefix", - "portable-atomic", - "unicode-width 0.2.0", - "web-time", -] - -[[package]] -name = "indoc" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" - -[[package]] -name = "indoc" -version = "2.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" - -[[package]] -name = "inotify" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" -dependencies = [ - "bitflags 1.3.2", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", -] - -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "block-padding", - "generic-array", -] - -[[package]] -name = "inquire" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fddf93031af70e75410a2511ec04d49e758ed2f26dad3404a934e0fb45cc12a" -dependencies = [ - "bitflags 2.6.0", - "crossterm", - "dyn-clone", - "fuzzy-matcher", - "fxhash", - "newline-converter", - "once_cell", - "unicode-segmentation", - "unicode-width 0.1.14", -] - -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "ip-info" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "prost 0.10.4", - "reqwest 0.12.12", - "rivet-operation", - "serde", - "serde_json", - "sqlx", -] - -[[package]] -name = "ipconfig" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" -dependencies = [ - "socket2 0.5.8", - "widestring", - "windows-sys 0.48.0", - "winreg", -] - -[[package]] -name = "ipnet" -version = "2.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" -dependencies = [ - "serde", -] - -[[package]] -name = "ipnetwork" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf466541e9d546596ee94f9f69590f89473455f88372423e0008fc1a7daf100e" -dependencies = [ - "serde", -] - -[[package]] -name = "is-macro" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d57a3e447e24c22647738e4607f1df1e0ec6f72e16182c4cd199f647cdfb0e4" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "itoa" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" - -[[package]] -name = "jni" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" -dependencies = [ - "cesu8", - "cfg-if", - "combine", - "jni-sys", - "log", - "thiserror 1.0.69", - "walkdir", - "windows-sys 0.45.0", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "job-gc" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "faker-job-run", - "futures-util", - "indoc 1.0.9", - "job-run", - "lazy_static", - "mm-lobby-for-run-id", - "mm-lobby-get", - "nomad-client", - "nomad-util", - "prost 0.10.4", - "rivet-config", - "rivet-connection", - "rivet-health-checks", - "rivet-metrics", - "rivet-operation", - "rivet-pools", - "rivet-runtime", - "serde_json", - "sqlx", - "tokio", - "tracing", - "tracing-logfmt", - "tracing-subscriber", - "uuid", -] - -[[package]] -name = "job-log-read" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "clickhouse", - "prost 0.10.4", - "rivet-operation", - "serde", -] - -[[package]] -name = "job-log-worker" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "clickhouse", - "reqwest 0.11.27", - "rivet-config", - "rivet-health-checks", - "rivet-metrics", - "rivet-runtime", - "s3-util", - "serde", - "upload-complete", - "upload-prepare", -] - -[[package]] -name = "job-run" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chirp-workflow", - "chrono", - "cjson", - "faker-job-run", - "faker-job-template", - "faker-region", - "hex", - "indoc 1.0.9", - "lazy_static", - "nomad-client", - "nomad-util", - "nomad_client", - "rand 0.8.5", - "region-get", - "reqwest 0.11.27", - "rivet-config", - "rivet-health-checks", - "rivet-metrics", - "rivet-operation", - "rivet-runtime", - "rivet-test", - "rivet-util-job", - "rustls 0.21.12", - "serde", - "serde_json", - "serde_urlencoded", - "sha2 0.10.8", - "sqlx", - "token-create", - "webpki 0.22.4", - "webpki-roots 0.22.6", -] - -[[package]] -name = "jobserver" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "json5" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" -dependencies = [ - "pest", - "pest_derive", - "serde", -] - -[[package]] -name = "jsonc-parser" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b558af6b49fd918e970471374e7a798b2c9bbcda624a210ffa3901ee5614bc8e" -dependencies = [ - "serde_json", -] - -[[package]] -name = "jsonwebtoken" -version = "8.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" -dependencies = [ - "base64 0.21.7", - "pem", - "ring 0.16.20", - "serde", - "serde_json", - "simple_asn1", -] - -[[package]] -name = "junction" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be39922b087cecaba4e2d5592dedfc8bda5d4a5a1231f143337cca207950b61d" -dependencies = [ - "scopeguard", - "winapi", -] - -[[package]] -name = "k256" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" -dependencies = [ - "cfg-if", - "ecdsa 0.16.9", - "elliptic-curve 0.13.8", - "once_cell", - "sha2 0.10.8", - "signature 2.2.0", -] - -[[package]] -name = "keccak" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" -dependencies = [ - "cpufeatures", -] - -[[package]] -name = "khronos-egl" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" -dependencies = [ - "libc", - "libloading 0.8.6", - "pkg-config", -] - -[[package]] -name = "khronos_api" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" - -[[package]] -name = "kqueue" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" -dependencies = [ - "kqueue-sys", - "libc", -] - -[[package]] -name = "kqueue-sys" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" -dependencies = [ - "bitflags 1.3.2", - "libc", -] - -[[package]] -name = "kv-str" -version = "25.5.2" -dependencies = [ - "anyhow", - "envy", - "serde", -] - -[[package]] -name = "lazy-regex" -version = "3.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60c7310b93682b36b98fa7ea4de998d3463ccbebd94d935d6b48ba5b6ffa7126" -dependencies = [ - "lazy-regex-proc_macros", - "once_cell", - "regex", -] - -[[package]] -name = "lazy-regex-proc_macros" -version = "3.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ba01db5ef81e17eb10a5e0f2109d1b3a3e29bac3070fdbd7d156bf7dbd206a1" -dependencies = [ - "proc-macro2", - "quote", - "regex", - "syn 2.0.90", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -dependencies = [ - "spin 0.9.8", -] - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "libc" -version = "0.2.171" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" - -[[package]] -name = "libffi" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce826c243048e3d5cec441799724de52e2d42f820468431fc3fceee2341871e2" -dependencies = [ - "libc", - "libffi-sys", -] - -[[package]] -name = "libffi-sys" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36115160c57e8529781b4183c2bb51fdc1f6d6d1ed345591d84be7703befb3c" -dependencies = [ - "cc", -] - -[[package]] -name = "libloading" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if", - "winapi", -] - -[[package]] -name = "libloading" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" -dependencies = [ - "cfg-if", - "windows-targets 0.52.6", -] - -[[package]] -name = "libm" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" - -[[package]] -name = "libredox" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" -dependencies = [ - "bitflags 2.6.0", - "libc", - "redox_syscall 0.5.7", -] - -[[package]] -name = "libsqlite3-sys" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" -dependencies = [ - "cc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "libssh2-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc8a030b787e2119a731f1951d6a773e2280c660f8ec4b0f5e1505a386e71ee" -dependencies = [ - "cc", - "libc", - "libz-sys", - "openssl-sys", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "libz-sys" -version = "1.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - -[[package]] -name = "linode" -version = "25.5.2" -dependencies = [ - "chirp-workflow", - "chrono", - "cluster", - "ipnet", - "rand 0.8.5", - "reqwest 0.12.12", - "rivet-config", - "serde", - "serde_json", - "sqlx", - "ssh-key", -] - -[[package]] -name = "linode-gc" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-workflow", - "chrono", - "cluster", - "linode", - "reqwest 0.12.12", - "rivet-config", - "rivet-connection", - "rivet-health-checks", - "rivet-metrics", - "rivet-runtime", - "serde", - "serde_json", - "sqlx", - "tokio", - "tracing", - "tracing-logfmt", - "tracing-subscriber", -] - -[[package]] -name = "linux-raw-sys" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" - -[[package]] -name = "litemap" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" - -[[package]] -name = "litrs" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" - -[[package]] -name = "load-test-api-cloud" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "faker-team", - "reqwest 0.11.27", - "rivet-api", - "rivet-config", - "rivet-connection", - "rivet-operation", - "rivet-runtime", - "token-create", - "tokio", - "tracing", - "tracing-logfmt", - "tracing-subscriber", - "user-identity-create", -] - -[[package]] -name = "load-test-mm" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "cloud-namespace-token-public-create", - "faker-build", - "faker-game", - "faker-game-namespace", - "faker-game-version", - "faker-region", - "mm-config-namespace-config-set", - "mm-lobby-list-for-namespace", - "mm-lobby-player-count", - "mm-player-count-for-namespace", - "region-get", - "reqwest 0.11.27", - "rivet-api", - "rivet-claims", - "rivet-config", - "rivet-connection", - "rivet-operation", - "rivet-runtime", - "token-create", - "tokio", - "tracing", - "tracing-logfmt", - "tracing-subscriber", -] - -[[package]] -name = "load-test-mm-sustain" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-build", - "faker-game", - "faker-game-namespace", - "faker-game-version", - "faker-region", - "faker-team", - "game-namespace-version-set", - "job-run", - "mm-config-version-get", - "mm-lobby-get", - "rand 0.8.5", - "reqwest 0.11.27", - "rivet-api", - "rivet-config", - "rivet-connection", - "rivet-operation", - "rivet-runtime", - "rivet-test", - "rivet-util-mm", - "token-create", - "tokio", - "tracing", - "tracing-logfmt", - "tracing-subscriber", - "user-identity-create", -] - -[[package]] -name = "load-test-sqlx" -version = "25.5.2" -dependencies = [ - "cdn-namespace-get", - "cdn-version-get", - "chirp-client", - "chirp-worker", - "mm-config-version-get", - "rivet-config", - "rivet-connection", - "rivet-health-checks", - "rivet-metrics", - "rivet-operation", - "rivet-runtime", - "sqlx", - "tokio", - "tracing", - "tracing-logfmt", - "tracing-subscriber", -] - -[[package]] -name = "load-test-watch-requests" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "faker-team", - "reqwest 0.11.27", - "rivet-api", - "rivet-config", - "rivet-connection", - "rivet-operation", - "rivet-runtime", - "token-create", - "tokio", - "tracing", - "tracing-logfmt", - "tracing-subscriber", - "user-identity-create", -] - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" - -[[package]] -name = "loom" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" -dependencies = [ - "cfg-if", - "generator", - "scoped-tls", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "lru" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" -dependencies = [ - "hashbrown 0.15.2", -] - -[[package]] -name = "lru-cache" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" -dependencies = [ - "linked-hash-map", -] - -[[package]] -name = "lz4" -version = "1.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d1febb2b4a79ddd1980eede06a8f7902197960aa0383ffcfdd62fe723036725" -dependencies = [ - "lz4-sys", -] - -[[package]] -name = "lz4-sys" -version = "1.11.1+lz4-1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bd8c0d6c6ed0cd30b3652886bb8711dc4bb01d637a68105a3d5158039b418e6" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "lz4_flex" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5" -dependencies = [ - "twox-hash", -] - -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - -[[package]] -name = "match_cfg" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" - -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata 0.1.10", -] - -[[package]] -name = "matchit" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" - -[[package]] -name = "matrixmultiply" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" -dependencies = [ - "autocfg", - "rawpointer", -] - -[[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" -dependencies = [ - "cfg-if", - "digest 0.10.7", -] - -[[package]] -name = "md4" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da5ac363534dce5fabf69949225e174fbf111a498bf0ff794c8ea1fba9f3dda" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "md5" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "memmap2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" -dependencies = [ - "libc", -] - -[[package]] -name = "memmem" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64a92489e2744ce060c349162be1c5f33c6969234104dbd99ddb5feb08b8c15" - -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - -[[package]] -name = "merkle_hash" -version = "3.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3edd3572d1a7b4e1b7ce5bb3af05405a8aeab2ec04b29d9779e72ad576ce4f38" -dependencies = [ - "blake3", - "camino", - "rayon", -] - -[[package]] -name = "metal" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5637e166ea14be6063a3f8ba5ccb9a4159df7d8f6d61c02fc3d480b1f90dcfcb" -dependencies = [ - "bitflags 2.6.0", - "block", - "core-graphics-types", - "foreign-types 0.5.0", - "log", - "objc", - "paste", -] - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "mime_guess" -version = "2.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" -dependencies = [ - "mime", - "unicase", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - -[[package]] -name = "miniz_oxide" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" -dependencies = [ - "adler2", - "simd-adler32", -] - -[[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", -] - -[[package]] -name = "mio" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" -dependencies = [ - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", -] - -[[package]] -name = "mm-config-game-get" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "mm-config-game-upsert" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "mm-config-lobby-group-get" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "faker-game-version", - "mm-config-version-get", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "mm-config-lobby-group-resolve-name-id" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-build", - "faker-game", - "faker-game-version", - "faker-region", - "prost 0.10.4", - "rivet-operation", - "rivet-util-mm", - "sqlx", -] - -[[package]] -name = "mm-config-lobby-group-resolve-version" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "faker-game-version", - "mm-config-version-get", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "mm-config-namespace-config-set" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-game", - "mm-config-namespace-config-validate", - "mm-config-namespace-get", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "mm-config-namespace-config-validate" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", -] - -[[package]] -name = "mm-config-namespace-create" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "mm-config-namespace-get" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "mm-config-namespace-create", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "mm-config-version-get" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-build", - "faker-game", - "faker-region", - "mm-config-version-prepare", - "mm-config-version-publish", - "prost 0.10.4", - "rivet-operation", - "rivet-util-mm", - "sqlx", -] - -[[package]] -name = "mm-config-version-prepare" -version = "25.5.2" -dependencies = [ - "build-get", - "chirp-client", - "chirp-worker", - "chirp-workflow", - "cluster", - "faker-build", - "faker-game", - "faker-region", - "heck 0.3.3", - "nomad-client", - "prost 0.10.4", - "region-get", - "reqwest 0.11.27", - "rivet-operation", - "rivet-util-build", - "rivet-util-job", - "rivet-util-mm", - "s3-util", - "sqlx", - "tier", - "upload-get", -] - -[[package]] -name = "mm-config-version-publish" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-build", - "faker-game", - "faker-region", - "mm-config-version-prepare", - "prost 0.10.4", - "rivet-operation", - "rivet-util-mm", - "sqlx", -] - -[[package]] -name = "mm-dev-player-token-create" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "token-create", -] - -[[package]] -name = "mm-gc" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "faker-mm-lobby", - "futures-util", - "indoc 1.0.9", - "lazy_static", - "mm-lobby-get", - "prost 0.10.4", - "region-list", - "rivet-config", - "rivet-connection", - "rivet-health-checks", - "rivet-metrics", - "rivet-operation", - "rivet-pools", - "rivet-runtime", - "rivet-util-mm", - "sqlx", - "tokio", - "tracing", - "tracing-logfmt", - "tracing-subscriber", -] - -[[package]] -name = "mm-lobby-find-fail" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "rivet-util-mm", -] - -[[package]] -name = "mm-lobby-find-lobby-query-list" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "rivet-util-mm", -] - -[[package]] -name = "mm-lobby-find-try-complete" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "prost 0.10.4", - "rivet-operation", - "rivet-util-mm", -] - -[[package]] -name = "mm-lobby-for-run-id" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-mm-lobby", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "mm-lobby-get" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "faker-mm-lobby", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "mm-lobby-history" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "faker-mm-lobby-row", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "mm-lobby-idle-update" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "faker-build", - "faker-game", - "faker-game-version", - "faker-region", - "game-namespace-get", - "game-namespace-version-set", - "lazy_static", - "mm-config-version-get", - "mm-lobby-get", - "prost 0.10.4", - "rivet-operation", - "rivet-util-mm", - "sqlx", -] - -[[package]] -name = "mm-lobby-list-for-namespace" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-mm-lobby", - "prost 0.10.4", - "rivet-operation", - "rivet-util-mm", - "sqlx", -] - -[[package]] -name = "mm-lobby-list-for-user-id" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-mm-lobby", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "mm-lobby-player-count" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-mm-lobby", - "prost 0.10.4", - "rivet-operation", - "rivet-util-mm", - "sqlx", -] - -[[package]] -name = "mm-lobby-runtime-aggregate" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "faker-game", - "faker-game-version", - "faker-mm-lobby", - "faker-mm-lobby-row", - "faker-region", - "mm-config-lobby-group-resolve-version", - "mm-config-version-get", - "prost 0.10.4", - "rivet-operation", - "rivet-util-mm", - "sqlx", -] - -[[package]] -name = "mm-lobby-state-get" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-mm-lobby", - "prost 0.10.4", - "rivet-operation", - "rivet-util-mm", - "sqlx", -] - -[[package]] -name = "mm-player-count-for-namespace" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-mm-lobby", - "prost 0.10.4", - "rivet-operation", - "rivet-util-mm", - "sqlx", -] - -[[package]] -name = "mm-player-get" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-mm-lobby", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] - -[[package]] -name = "mm-worker" -version = "25.5.2" -dependencies = [ - "build-get", - "chirp-client", - "chirp-worker", - "chirp-workflow", - "chrono", - "cluster", - "csv", - "faker-build", - "faker-game", - "faker-game-namespace", - "faker-game-version", - "faker-mm-lobby", - "faker-region", - "faker-user", - "game-get", - "game-namespace-get", - "game-namespace-version-set", - "game-version-get", - "heck 0.3.3", - "http 0.2.12", - "job-run", - "lazy_static", - "maplit", - "mm-config-game-get", - "mm-config-lobby-group-resolve-version", - "mm-config-namespace-config-set", - "mm-config-namespace-get", - "mm-config-version-get", - "mm-lobby-find-fail", - "mm-lobby-find-lobby-query-list", - "mm-lobby-find-try-complete", - "mm-lobby-get", - "mm-lobby-idle-update", - "mm-lobby-player-count", - "mm-lobby-state-get", - "mm-player-count-for-namespace", - "nomad-client", - "nomad-util", - "redis-util", - "regex", - "region-get", - "reqwest 0.11.27", - "rivet-config", - "rivet-health-checks", - "rivet-metrics", - "rivet-runtime", - "rivet-test", - "rivet-util-build", - "rivet-util-job", - "rivet-util-mm", - "s3-util", - "serde", - "sqlx", - "team-get", - "tier", - "token-create", - "upload-complete", - "upload-get", - "upload-prepare", - "user-identity-create", -] - -[[package]] -name = "moka" -version = "0.12.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9321642ca94a4282428e6ea4af8cc2ca4eac48ac7a6a4ea8f33f76d0ce70926" -dependencies = [ - "async-lock", - "crossbeam-channel", - "crossbeam-epoch", - "crossbeam-utils", - "event-listener", - "futures-util", - "loom", - "parking_lot 0.12.3", - "portable-atomic", - "rustc_version 0.4.1", - "smallvec", - "tagptr", - "thiserror 1.0.69", - "uuid", -] - -[[package]] -name = "monch" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b52c1b33ff98142aecea13138bd399b68aa7ab5d9546c300988c345004001eea" - -[[package]] -name = "monolith-worker" -version = "25.5.2" -dependencies = [ - "cdn-worker", - "cf-custom-hostname-worker", - "chirp-client", - "cloud-worker", - "external-worker", - "job-log-worker", - "job-run", - "mm-worker", - "rivet-config", - "rivet-connection", - "rivet-health-checks", - "rivet-metrics", - "rivet-operation", - "rivet-runtime", - "team-invite-worker", - "team-worker", - "tokio", - "tracing", - "tracing-subscriber", - "upload-worker", - "user-worker", -] - -[[package]] -name = "monolith-workflow-worker" -version = "25.5.2" -dependencies = [ - "chirp-workflow", - "cluster", - "job-run", - "linode", - "rivet-config", - "rivet-health-checks", - "rivet-metrics", - "rivet-runtime", -] - -[[package]] -name = "multimap" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" - -[[package]] -name = "naga" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e536ae46fcab0876853bd4a632ede5df4b1c2527a58f6c5a4150fe86be858231" -dependencies = [ - "arrayvec 0.7.6", - "bit-set", - "bitflags 2.6.0", - "codespan-reporting", - "hexf-parse", - "indexmap 2.7.0", - "log", - "num-traits", - "rustc-hash 1.1.0", - "serde", - "spirv", - "termcolor", - "thiserror 1.0.69", - "unicode-xid", -] - -[[package]] -name = "nalgebra" -version = "0.33.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26aecdf64b707efd1310e3544d709c5c0ac61c13756046aaaba41be5c4f66a3b" -dependencies = [ - "approx", - "matrixmultiply", - "num-complex", - "num-rational", - "num-traits", - "rand 0.8.5", - "rand_distr", - "simba", - "typenum", -] - -[[package]] -name = "napi_sym" -version = "0.110.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "quote", - "serde", - "serde_json", - "syn 2.0.90", -] - -[[package]] -name = "native-tls" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework 2.11.1", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - -[[package]] -name = "ndk-sys" -version = "0.5.0+25.2.9519653" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" -dependencies = [ - "jni-sys", -] - -[[package]] -name = "netif" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29a01b9f018d6b7b277fef6c79fdbd9bf17bb2d1e298238055cafab49baa5ee" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "new_debug_unreachable" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" - -[[package]] -name = "newline-converter" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b6b097ecb1cbfed438542d16e84fd7ad9b0c76c8a65b7f9039212a3d14dc7f" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "nibble_vec" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" -dependencies = [ - "smallvec", -] - -[[package]] -name = "nix" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" -dependencies = [ - "bitflags 2.6.0", - "cfg-if", - "libc", -] - -[[package]] -name = "nix" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" -dependencies = [ - "bitflags 2.6.0", - "cfg-if", - "cfg_aliases 0.2.1", - "libc", -] - -[[package]] -name = "nix" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" -dependencies = [ - "bitflags 2.6.0", - "cfg-if", - "cfg_aliases 0.2.1", - "libc", -] - -[[package]] -name = "nkeys" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aad178aad32087b19042ee36dfd450b73f5f934fbfb058b59b198684dfec4c47" -dependencies = [ - "byteorder", - "data-encoding", - "ed25519", - "ed25519-dalek", - "getrandom 0.2.15", - "log", - "rand 0.8.5", - "signatory", -] - -[[package]] -name = "no-std-compat" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" - -[[package]] -name = "node_resolver" -version = "0.19.0" -source = "git+https://github.com/rivet-gg/deno?rev=a6903d67063e07b82836399f63c7a0fa5be8bf56#a6903d67063e07b82836399f63c7a0fa5be8bf56" -dependencies = [ - "anyhow", - "async-trait", - "boxed_error", - "deno_media_type 0.2.2", - "deno_package_json", - "deno_path_util", - "futures", - "lazy-regex", - "once_cell", - "path-clean", - "regex", - "serde_json", - "thiserror 1.0.69", - "tokio", - "url", -] - -[[package]] -name = "nom" -version = "5.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08959a387a676302eebf4ddbcbc611da04285579f76f88ee0506c63b1a61dd4b" -dependencies = [ - "memchr", - "version_check", -] - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "nomad-client" -version = "0.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1548b7290f5a088b0e1069fb41e2d91a5c2c143b1a26bd9327c0fa4a17216bab" -dependencies = [ - "reqwest 0.11.27", - "serde", - "serde_derive", - "serde_json", - "url", -] - -[[package]] -name = "nomad-monitor" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "chirp-workflow", - "chrono", - "cluster", - "futures-util", - "indoc 1.0.9", - "lazy_static", - "nomad-util", - "nomad_client", - "prost 0.10.4", - "rivet-config", - "rivet-connection", - "rivet-health-checks", - "rivet-metrics", - "rivet-operation", - "rivet-pools", - "rivet-runtime", - "rivet-util-job", - "serde", - "serde_json", - "tokio", - "tracing", - "tracing-logfmt", - "tracing-subscriber", -] - -[[package]] -name = "nomad-util" -version = "25.5.2" -dependencies = [ - "base64 0.13.1", - "bytes", - "futures-util", - "global-error", - "nomad-client", - "nomad_client", - "reqwest 0.12.12", - "rivet-config", - "rivet-pools", - "serde", - "serde_json", - "thiserror 1.0.69", - "tokio", - "tracing", -] - -[[package]] -name = "nomad_client" -version = "1.1.4" -source = "git+https://github.com/rivet-gg/nomad-client?rev=abb66bf#abb66bf0c30c7ff5b0c695dae952481c33e538b5" -dependencies = [ - "reqwest 0.11.27", - "serde", - "serde_derive", - "serde_json", - "url", -] - -[[package]] -name = "nonzero_ext" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" - -[[package]] -name = "notify" -version = "6.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" -dependencies = [ - "bitflags 2.6.0", - "crossbeam-channel", - "filetime", - "fsevent-sys", - "inotify", - "kqueue", - "libc", - "log", - "mio 0.8.11", - "serde", - "walkdir", - "windows-sys 0.48.0", -] - -[[package]] -name = "ntapi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" -dependencies = [ - "winapi", -] - -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "nu-ansi-term" -version = "0.50.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "nuid" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc895af95856f929163a0aa20c26a78d26bfdc839f51b9d5aa7a5b79e52b7e83" -dependencies = [ - "rand 0.8.5", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", - "rand 0.8.5", - "serde", -] - -[[package]] -name = "num-bigint-dig" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" -dependencies = [ - "byteorder", - "lazy_static", - "libm", - "num-integer", - "num-iter", - "num-traits", - "rand 0.8.5", - "serde", - "smallvec", - "zeroize", -] - -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_threads" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" -dependencies = [ - "libc", -] - -[[package]] -name = "number_prefix" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" - -[[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", -] - -[[package]] -name = "objc-sys" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" - -[[package]] -name = "objc2" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" -dependencies = [ - "objc-sys", - "objc2-encode", -] - -[[package]] -name = "objc2-encode" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" - -[[package]] -name = "objc2-foundation" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" -dependencies = [ - "bitflags 2.6.0", - "block2", - "libc", - "objc2", -] - -[[package]] -name = "object" -version = "0.36.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" -dependencies = [ - "memchr", -] - -[[package]] -name = "oid-registry" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" -dependencies = [ - "asn1-rs", -] - -[[package]] -name = "once_cell" -version = "1.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" - -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - -[[package]] -name = "openssl" -version = "0.10.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" -dependencies = [ - "bitflags 2.6.0", - "cfg-if", - "foreign-types 0.3.2", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "opentelemetry" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab70038c28ed37b97d8ed414b6429d343a8bbf44c9f79ec854f3a643029ba6d7" -dependencies = [ - "futures-core", - "futures-sink", - "js-sys", - "pin-project-lite", - "thiserror 1.0.69", - "tracing", -] - -[[package]] -name = "opentelemetry" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "236e667b670a5cdf90c258f5a55794ec5ac5027e960c224bff8367a59e1e6426" -dependencies = [ - "futures-core", - "futures-sink", - "js-sys", - "pin-project-lite", - "thiserror 2.0.12", - "tracing", -] - -[[package]] -name = "opentelemetry-appender-tracing" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c513c7af3bec30113f3d4620134ff923295f1e9c580fda2b8abe0831f925ddc0" -dependencies = [ - "opentelemetry 0.28.0", - "tracing", - "tracing-core", - "tracing-subscriber", -] - -[[package]] -name = "opentelemetry-http" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a8a7f5f6ba7c1b286c2fbca0454eaba116f63bbe69ed250b642d36fbb04d80" -dependencies = [ - "async-trait", - "bytes", - "http 1.1.0", - "opentelemetry 0.27.1", -] - -[[package]] -name = "opentelemetry-http" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8863faf2910030d139fb48715ad5ff2f35029fc5f244f6d5f689ddcf4d26253" -dependencies = [ - "async-trait", - "bytes", - "http 1.1.0", - "opentelemetry 0.28.0", - "reqwest 0.12.12", - "tracing", -] - -[[package]] -name = "opentelemetry-otlp" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cf61a1868dacc576bf2b2a1c3e9ab150af7272909e80085c3173384fe11f76" -dependencies = [ - "async-trait", - "futures-core", - "http 1.1.0", - "opentelemetry 0.27.1", - "opentelemetry-http 0.27.0", - "opentelemetry-proto 0.27.0", - "opentelemetry_sdk 0.27.1", - "prost 0.13.4", - "serde_json", - "thiserror 1.0.69", - "tokio", - "tonic", - "tracing", -] - -[[package]] -name = "opentelemetry-otlp" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bef114c6d41bea83d6dc60eb41720eedd0261a67af57b66dd2b84ac46c01d91" -dependencies = [ - "async-trait", - "futures-core", - "http 1.1.0", - "opentelemetry 0.28.0", - "opentelemetry-http 0.28.0", - "opentelemetry-proto 0.28.0", - "opentelemetry_sdk 0.28.0", - "prost 0.13.4", - "reqwest 0.12.12", - "thiserror 2.0.12", - "tokio", - "tonic", - "tracing", -] - -[[package]] -name = "opentelemetry-proto" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6e05acbfada5ec79023c85368af14abd0b307c015e9064d249b2a950ef459a6" -dependencies = [ - "hex", - "opentelemetry 0.27.1", - "opentelemetry_sdk 0.27.1", - "prost 0.13.4", - "serde", - "tonic", -] - -[[package]] -name = "opentelemetry-proto" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f8870d3024727e99212eb3bb1762ec16e255e3e6f58eeb3dc8db1aa226746d" -dependencies = [ - "opentelemetry 0.28.0", - "opentelemetry_sdk 0.28.0", - "prost 0.13.4", - "tonic", -] - -[[package]] -name = "opentelemetry-semantic-conventions" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc1b6902ff63b32ef6c489e8048c5e253e2e4a803ea3ea7e783914536eb15c52" - -[[package]] -name = "opentelemetry-semantic-conventions" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fb3a2f78c2d55362cd6c313b8abedfbc0142ab3c2676822068fd2ab7d51f9b7" - -[[package]] -name = "opentelemetry-stdout" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb0e5a5132e4b80bf037a78e3e12c8402535199f5de490d0c38f7eac71bc831" -dependencies = [ - "async-trait", - "chrono", - "futures-util", - "opentelemetry 0.28.0", - "opentelemetry_sdk 0.28.0", - "serde", - "thiserror 2.0.12", -] - -[[package]] -name = "opentelemetry_sdk" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "231e9d6ceef9b0b2546ddf52335785ce41252bc7474ee8ba05bfad277be13ab8" -dependencies = [ - "async-trait", - "futures-channel", - "futures-executor", - "futures-util", - "glob", - "opentelemetry 0.27.1", - "percent-encoding", - "rand 0.8.5", - "serde_json", - "thiserror 1.0.69", - "tracing", -] - -[[package]] -name = "opentelemetry_sdk" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84dfad6042089c7fc1f6118b7040dc2eb4ab520abbf410b79dc481032af39570" -dependencies = [ - "async-trait", - "futures-channel", - "futures-executor", - "futures-util", - "glob", - "opentelemetry 0.28.0", - "percent-encoding", - "rand 0.8.5", - "serde_json", - "thiserror 2.0.12", - "tracing", -] - -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - -[[package]] -name = "ordered-float" -version = "2.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" -dependencies = [ - "num-traits", -] - -[[package]] -name = "os_pipe" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57119c3b893986491ec9aa85056780d3a0f3cf4da7cc09dd3650dbd6c6738fb9" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "outref" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f222829ae9293e33a9f5e9f440c6760a3d450a64affe1846486b140db81c1f4" - -[[package]] -name = "outref" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4030760ffd992bef45b0ae3f10ce1aba99e33464c90d14dd7c039884963ddc7a" - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "p224" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30c06436d66652bc2f01ade021592c80a2aad401570a18aa18b82e440d2b9aa1" -dependencies = [ - "ecdsa 0.16.9", - "elliptic-curve 0.13.8", - "primeorder", - "sha2 0.10.8", -] - -[[package]] -name = "p256" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" -dependencies = [ - "ecdsa 0.14.8", - "elliptic-curve 0.12.3", - "sha2 0.10.8", -] - -[[package]] -name = "p256" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" -dependencies = [ - "ecdsa 0.16.9", - "elliptic-curve 0.13.8", - "primeorder", - "sha2 0.10.8", -] - -[[package]] -name = "p384" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" -dependencies = [ - "ecdsa 0.16.9", - "elliptic-curve 0.13.8", - "primeorder", - "sha2 0.10.8", -] - -[[package]] -name = "p521" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2" -dependencies = [ - "base16ct 0.2.0", - "ecdsa 0.16.9", - "elliptic-curve 0.13.8", - "primeorder", - "rand_core 0.6.4", - "sha2 0.10.8", -] - -[[package]] -name = "papaya" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6827e3fc394523c21d4464d02c0bb1c19966ea4a58a9844ad6d746214179d2bc" -dependencies = [ - "equivalent", - "seize", -] - -[[package]] -name = "papergrid" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b0f8def1f117e13c895f3eda65a7b5650688da29d6ad04635f61bc7b92eebd" -dependencies = [ - "ansi-str", - "ansitok", - "bytecount", - "fnv", - "unicode-width 0.2.0", -] - -[[package]] -name = "parking" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core 0.9.10", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.5.7", - "smallvec", - "windows-targets 0.52.6", -] - -[[package]] -name = "parse-display" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914a1c2265c98e2446911282c6ac86d8524f495792c38c5bd884f80499c7538a" -dependencies = [ - "parse-display-derive", - "regex", - "regex-syntax 0.8.5", -] - -[[package]] -name = "parse-display-derive" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ae7800a4c974efd12df917266338e79a7a74415173caf7e70aa0a0707345281" -dependencies = [ - "proc-macro2", - "quote", - "regex", - "regex-syntax 0.8.5", - "structmeta", - "syn 2.0.90", -] - -[[package]] -name = "password-hash" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" -dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "path-clean" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecba01bf2678719532c5e3059e0b5f0811273d94b397088b82e3bd0a78c78fdd" - -[[package]] -name = "pathdiff" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" - -[[package]] -name = "pbkdf2" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" -dependencies = [ - "digest 0.10.7", - "hmac 0.12.1", -] - -[[package]] -name = "pegboard" -version = "25.5.2" -dependencies = [ - "anyhow", - "build", - "chirp-workflow", - "clickhouse-user-query", - "cluster", - "fdb-util", - "foundationdb", - "game-get", - "game-namespace-get", - "game-resolve-namespace-id", - "heck 0.3.3", - "lazy_static", - "nix 0.30.1", - "once_cell", - "rand 0.8.5", - "regex", - "reqwest 0.12.12", - "rivet-api", - "rivet-config", - "rivet-convert", - "rivet-metrics", - "rivet-operation", - "rivet-util", - "s3-util", - "schemars", - "serde", - "serde_json", - "serde_urlencoded", - "server-spec", - "sqlx", - "strum 0.24.1", - "thiserror 1.0.69", - "tier", - "token-create", - "upload-complete", - "upload-get", - "upload-prepare", - "uuid", -] - -[[package]] -name = "pegboard-actor-kv" -version = "0.1.0" -dependencies = [ - "anyhow", - "deno_core", - "fdb-util", - "foundationdb", - "futures-util", - "indexmap 2.7.0", - "prost 0.13.4", - "serde", - "serde_json", - "tokio", - "tokio-tungstenite 0.23.1", - "tracing", - "tracing-logfmt", - "tracing-subscriber", - "uuid", -] - -[[package]] -name = "pegboard-config" -version = "25.5.2" -dependencies = [ - "pegboard", - "schemars", - "serde", - "url", - "uuid", -] - -[[package]] -name = "pegboard-container-runner" -version = "25.5.2" -dependencies = [ - "anyhow", - "nix 0.30.1", - "portpicker", - "rivet-logs", - "serde", - "serde_json", - "signal-hook", - "tempfile", - "uuid", -] - -[[package]] -name = "pegboard-echo-server" -version = "0.0.1" -dependencies = [ - "tiny_http", -] - -[[package]] -name = "pegboard-isolate-v8-runner" -version = "25.5.2" -dependencies = [ - "anyhow", - "deno_ast 0.42.2", - "deno_core", - "deno_runtime", - "fdb-util", - "foundationdb", - "futures-util", - "netif", - "nix 0.30.1", - "pegboard", - "pegboard-actor-kv", - "pegboard-config", - "portpicker", - "rivet-api", - "rivet-convert", - "rivet-logs", - "rivet-runtime", - "rustls 0.23.25", - "serde", - "serde_json", - "service-discovery", - "signal-hook", - "tempfile", - "tokio", - "tokio-tungstenite 0.23.1", - "tracing", - "tracing-logfmt", - "tracing-subscriber", - "twox-hash", - "uuid", -] - -[[package]] -name = "pegboard-manager" -version = "25.5.2" -dependencies = [ - "anyhow", - "bytes", - "futures-util", - "hyper 0.14.31", - "indoc 2.0.5", - "json5", - "lazy_static", - "nix 0.30.1", - "notify", - "pegboard", - "pegboard-config", - "portpicker", - "prometheus", - "rand 0.8.5", - "rand_chacha 0.3.1", - "reqwest 0.12.12", - "rivet-logs", - "rivet-util", - "serde", - "serde_json", - "serde_yaml", - "service-discovery", - "sqlx", - "sysinfo 0.31.4", - "tempfile", - "thiserror 1.0.69", - "tokio", - "tokio-tungstenite 0.23.1", - "tokio-util 0.7.12", - "tracing", - "tracing-logfmt", - "tracing-subscriber", - "url", - "uuid", -] - -[[package]] -name = "pegboard-usage-metrics-publish" -version = "25.5.2" -dependencies = [ - "build", - "chirp-client", - "chirp-workflow", - "cluster", - "fdb-util", - "foundationdb", - "pegboard", - "rivet-config", - "rivet-connection", - "rivet-health-checks", - "rivet-metrics", - "rivet-runtime", - "sqlx", - "tokio", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "pegboard-ws" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-workflow", - "hyper 1.6.0", - "pegboard", - "rivet-config", - "rivet-connection", - "rivet-health-checks", - "rivet-metrics", - "rivet-runtime", - "serde", - "tokio-tungstenite 0.23.1", - "url", -] - -[[package]] -name = "pem" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" -dependencies = [ - "base64 0.13.1", -] - -[[package]] -name = "pem-rfc7468" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" -dependencies = [ - "base64ct", -] - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pest" -version = "2.7.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" -dependencies = [ - "memchr", - "thiserror 1.0.69", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.7.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.7.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "pest_meta" -version = "2.7.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d" -dependencies = [ - "once_cell", - "pest", - "sha2 0.10.8", -] - -[[package]] -name = "petgraph" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" -dependencies = [ - "fixedbitset", - "indexmap 2.7.0", -] - -[[package]] -name = "phf" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" -dependencies = [ - "phf_macros", - "phf_shared", -] - -[[package]] -name = "phf_generator" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" -dependencies = [ - "phf_shared", - "rand 0.8.5", -] - -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "phf_shared" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pin-project" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" +name = "async-trait" +version = "0.1.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkcs1" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" -dependencies = [ - "der 0.7.9", - "pkcs8 0.10.2", - "spki 0.7.3", -] - -[[package]] -name = "pkcs5" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6" -dependencies = [ - "aes", - "cbc", - "der 0.7.9", - "pbkdf2", - "scrypt", - "sha2 0.10.8", - "spki 0.7.3", + "syn 2.0.104", ] [[package]] -name = "pkcs8" -version = "0.9.0" +name = "atomic-waker" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" -dependencies = [ - "der 0.6.1", - "spki 0.6.0", -] +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] -name = "pkcs8" -version = "0.10.2" +name = "auto-future" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der 0.7.9", - "pkcs5", - "rand_core 0.6.4", - "spki 0.7.3", -] +checksum = "3c1e7e457ea78e524f48639f551fd79703ac3f2237f5ecccdf4708f8a75ad373" [[package]] -name = "pkg-config" -version = "0.3.31" +name = "autocfg" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] -name = "pkg-version" -version = "1.0.0" +name = "axum" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e848f61ee4b2010345e65757e427a077213af1cee5d3e6a02e4a151dabca377" +checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" dependencies = [ - "pkg-version-impl", - "proc-macro-hack", + "async-trait", + "axum-core 0.4.5", + "bytes", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "itoa 1.0.15", + "matchit 0.7.3", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper", + "tower 0.5.2", + "tower-layer", + "tower-service", ] [[package]] -name = "pkg-version-impl" -version = "0.1.1" +name = "axum" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1564bf5d476bf4a5eac420b88c500454c000dca79cef0a2e4304a1fe34361a3b" +checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" dependencies = [ - "proc-macro-hack", + "axum-core 0.5.2", + "bytes", + "form_urlencoded", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "hyper 1.6.0", + "hyper-util", + "itoa 1.0.15", + "matchit 0.8.4", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tower 0.5.2", + "tower-layer", + "tower-service", + "tracing", ] [[package]] -name = "png" -version = "0.17.16" +name = "axum-core" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ - "bitflags 1.3.2", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide 0.8.0", + "async-trait", + "bytes", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper", + "tower-layer", + "tower-service", ] [[package]] -name = "polyval" -version = "0.6.2" +name = "axum-core" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" dependencies = [ - "cfg-if", - "cpufeatures", - "opaque-debug", - "universal-hash", + "bytes", + "futures-core", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper", + "tower-layer", + "tower-service", + "tracing", ] [[package]] -name = "portable-atomic" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" - -[[package]] -name = "portpicker" -version = "0.1.1" +name = "axum-test" +version = "17.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be97d76faf1bfab666e1375477b23fde79eccf0276e9b63b92a39d676a889ba9" -dependencies = [ - "rand 0.8.5", -] - -[[package]] -name = "posthog-core" -version = "0.1.0" -source = "git+https://github.com/rivet-gg/posthog-rs?rev=ef4e80e#ef4e80e57747ea7204794bce9a103bfeccefabf1" +checksum = "0eb1dfb84bd48bad8e4aa1acb82ed24c2bb5e855b659959b4e03b4dca118fcac" dependencies = [ - "chrono", + "anyhow", + "assert-json-diff", + "auto-future", + "axum 0.8.4", + "bytes", + "bytesize", + "cookie", + "http 1.3.1", + "http-body-util", + "hyper 1.6.0", + "hyper-util", + "mime", + "pretty_assertions", + "reserve-port", + "rust-multipart-rfc7578_2", "serde", "serde_json", - "thiserror 1.0.69", + "serde_urlencoded", + "smallvec", + "tokio", + "tower 0.5.2", + "url", ] [[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.20" +name = "backtrace" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ - "zerocopy 0.7.35", + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] -name = "predicates" -version = "3.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97" +name = "bare_gen" +version = "0.0.1" dependencies = [ - "anstyle", - "difflib", - "predicates-core", + "heck 0.5.0", + "pest", + "pest_derive", + "proc-macro2", + "quote", + "serde", + "syn 2.0.104", ] [[package]] -name = "predicates-core" -version = "1.0.8" +name = "base64" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] -name = "predicates-tree" -version = "1.0.11" +name = "base64" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13" -dependencies = [ - "predicates-core", - "termtree", -] +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] -name = "prettyplease" -version = "0.1.25" +name = "base64" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" -dependencies = [ - "proc-macro2", - "syn 1.0.109", -] +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] -name = "prettyplease" -version = "0.2.25" +name = "base64ct" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" -dependencies = [ - "proc-macro2", - "syn 2.0.90", -] +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" [[package]] -name = "primeorder" -version = "0.13.6" +name = "bcrypt" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +checksum = "a7e7c93a3fb23b2fdde989b2c9ec4dd153063ec81f408507f84c090cd91c6641" dependencies = [ - "elliptic-curve 0.13.8", + "base64 0.13.1", + "blowfish", + "getrandom 0.2.16", + "zeroize", ] [[package]] -name = "proc-macro-error" -version = "1.0.4" +name = "bindgen" +version = "0.72.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +checksum = "4f72209734318d0b619a5e0f5129918b848c416e122a3c4ce054e03cb87b726f" dependencies = [ - "proc-macro-error-attr", + "bitflags", + "cexpr", + "clang-sys", + "itertools 0.13.0", "proc-macro2", "quote", - "syn 1.0.109", - "version_check", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.104", ] [[package]] -name = "proc-macro-error-attr" -version = "1.0.4" +name = "bitflags" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] -name = "proc-macro-error-attr2" -version = "2.0.0" +name = "block-buffer" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "proc-macro2", - "quote", + "generic-array", ] [[package]] -name = "proc-macro-error2" -version = "2.0.1" +name = "blowfish" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7" dependencies = [ - "proc-macro-error-attr2", - "proc-macro2", - "quote", - "syn 2.0.90", + "byteorder", + "cipher", ] [[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" - -[[package]] -name = "proc-macro-rules" -version = "0.4.0" +name = "bstr" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c277e4e643ef00c1233393c673f655e3672cf7eb3ba08a00bdd0ea59139b5f" +checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" dependencies = [ - "proc-macro-rules-macros", - "proc-macro2", - "syn 2.0.90", + "memchr", ] [[package]] -name = "proc-macro-rules-macros" -version = "0.4.0" +name = "bumpalo" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "207fffb0fe655d1d47f6af98cc2793405e85929bdbc420d685554ff07be27ac7" -dependencies = [ - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.90", -] +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] -name = "proc-macro2" -version = "1.0.92" +name = "bytecount" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" -dependencies = [ - "unicode-ident", -] +checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" [[package]] -name = "profiling" -version = "1.0.16" +name = "bytemuck" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" +checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" [[package]] -name = "prometheus" -version = "0.13.4" +name = "byteorder" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" -dependencies = [ - "cfg-if", - "fnv", - "lazy_static", - "memchr", - "parking_lot 0.12.3", - "protobuf", - "thiserror 1.0.69", -] +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] -name = "prost" -version = "0.10.4" +name = "bytes" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71adf41db68aa0daaefc69bb30bcd68ded9b9abaad5d1fbb6304c4fb390e083e" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" dependencies = [ - "bytes", - "prost-derive 0.10.1", + "serde", ] [[package]] -name = "prost" -version = "0.11.9" +name = "bytesize" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" -dependencies = [ - "bytes", - "prost-derive 0.11.9", -] +checksum = "a3c8f83209414aacf0eeae3cf730b18d6981697fba62f200fcfb92b9f082acba" [[package]] -name = "prost" -version = "0.12.6" +name = "bzip2-sys" +version = "0.1.13+1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" +checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" dependencies = [ - "bytes", - "prost-derive 0.12.6", + "cc", + "pkg-config", ] [[package]] -name = "prost" -version = "0.13.4" +name = "cc" +version = "1.2.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c0fef6c4230e4ccf618a35c59d7ede15dea37de8427500f50aff708806e42ec" +checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7" dependencies = [ - "bytes", - "prost-derive 0.13.4", + "jobserver", + "libc", + "shlex", ] [[package]] -name = "prost-build" -version = "0.11.9" +name = "cexpr" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ - "bytes", - "heck 0.4.1", - "itertools 0.10.5", - "lazy_static", - "log", - "multimap", - "petgraph", - "prettyplease 0.1.25", - "prost 0.11.9", - "prost-types 0.11.9", - "regex", - "syn 1.0.109", - "tempfile", - "which 4.4.2", + "nom", ] [[package]] -name = "prost-build" -version = "0.13.4" +name = "cfg-if" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0f3e5beed80eb580c68e2c600937ac2c4eedabdfd5ef1e5b7ea4f3fba84497b" -dependencies = [ - "heck 0.5.0", - "itertools 0.12.1", - "log", - "multimap", - "once_cell", - "petgraph", - "prettyplease 0.2.25", - "prost 0.13.4", - "prost-types 0.13.4", - "regex", - "syn 2.0.90", - "tempfile", -] +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] -name = "prost-derive" -version = "0.10.1" +name = "cfg_aliases" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b670f45da57fb8542ebdbb6105a925fe571b67f9e7ed9f47a06a84e72b4e7cc" -dependencies = [ - "anyhow", - "itertools 0.10.5", - "proc-macro2", - "quote", - "syn 1.0.109", -] +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] -name = "prost-derive" -version = "0.11.9" +name = "chrono" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" dependencies = [ - "anyhow", - "itertools 0.10.5", - "proc-macro2", - "quote", - "syn 1.0.109", + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-link", ] [[package]] -name = "prost-derive" -version = "0.12.6" +name = "cipher" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "anyhow", - "itertools 0.12.1", - "proc-macro2", - "quote", - "syn 2.0.90", + "crypto-common", + "inout", ] [[package]] -name = "prost-derive" -version = "0.13.4" +name = "cjson" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "157c5a9d7ea5c2ed2d9fb8f495b64759f7816c7eaea54ba3978f0d63000162e3" +checksum = "91531b1d3fe15c6126decd9977dc823e1fde8e2501cf6ac780407f952a28f7ce" dependencies = [ - "anyhow", - "itertools 0.12.1", - "proc-macro2", - "quote", - "syn 2.0.90", + "itoa 0.4.8", + "serde", + "serde_derive", + "serde_json", ] [[package]] -name = "prost-types" -version = "0.10.1" +name = "clang-sys" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d0a014229361011dc8e69c8a1ec6c2e8d0f2af7c91e3ea3f5b2170298461e68" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ - "bytes", - "prost 0.10.4", + "glob", + "libc", + "libloading", ] [[package]] -name = "prost-types" -version = "0.11.9" +name = "clap" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9" dependencies = [ - "prost 0.11.9", + "clap_builder", + "clap_derive", ] [[package]] -name = "prost-types" -version = "0.12.6" +name = "clap_builder" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d" dependencies = [ - "prost 0.12.6", + "anstream", + "anstyle", + "clap_lex", + "strsim 0.11.1", + "terminal_size", ] [[package]] -name = "prost-types" -version = "0.13.4" +name = "clap_derive" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2f1e56baa61e93533aebc21af4d2134b70f66275e0fcdf3cbe43d77ff7e8fc" +checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491" dependencies = [ - "prost 0.13.4", + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "protobuf" -version = "2.28.0" +name = "clap_lex" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] -name = "protobuf-src" -version = "1.1.0+21.5" +name = "clickhouse" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7ac8852baeb3cc6fb83b93646fb93c0ffe5d14bf138c945ceb4b9948ee0e3c1" +checksum = "a0875e527e299fc5f4faba42870bf199a39ab0bb2dbba1b8aef0a2151451130f" dependencies = [ - "autotools", + "bstr", + "bytes", + "clickhouse-derive", + "clickhouse-rs-cityhash-sys", + "futures", + "hyper 0.14.32", + "hyper-tls 0.5.0", + "lz4", + "sealed", + "serde", + "static_assertions", + "thiserror 1.0.69", + "tokio", + "url", + "uuid", ] [[package]] -name = "psm" -version = "0.1.24" +name = "clickhouse-derive" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810" +checksum = "18af5425854858c507eec70f7deb4d5d8cec4216fcb086283a78872387281ea5" dependencies = [ - "cc", + "proc-macro2", + "quote", + "serde_derive_internals 0.26.0", + "syn 1.0.109", ] [[package]] -name = "ptr_meta" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +name = "clickhouse-inserter" +version = "0.0.1" dependencies = [ - "ptr_meta_derive", + "anyhow", + "async-channel", + "reqwest", + "serde", + "serde_json", + "thiserror 1.0.69", + "tokio", + "tokio-util", + "tracing", ] [[package]] -name = "ptr_meta_derive" -version = "0.1.4" +name = "clickhouse-rs-cityhash-sys" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +checksum = "4baf9d4700a28d6cb600e17ed6ae2b43298a5245f1f76b4eab63027ebfd592b9" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "cc", ] [[package]] -name = "quanta" -version = "0.12.3" +name = "clickhouse-user-query" +version = "0.0.1" +dependencies = [ + "clickhouse", + "serde", + "serde_json", + "thiserror 1.0.69", + "tokio", +] + +[[package]] +name = "clipboard-win" +version = "5.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5" +checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4" dependencies = [ - "crossbeam-utils", - "libc", - "once_cell", - "raw-cpuid", - "wasi 0.11.0+wasi-snapshot-preview1", - "web-sys", - "winapi", + "error-code", ] [[package]] -name = "quick-error" -version = "1.2.3" +name = "colorchoice" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] -name = "quick-xml" -version = "0.18.1" +name = "colored_json" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cc440ee4802a86e357165021e3e255a9143724da31db1e2ea540214c96a0f82" +checksum = "e35980a1b846f8e3e359fd18099172a0857140ba9230affc4f71348081e039b6" dependencies = [ - "memchr", + "serde", + "serde_json", + "yansi", ] [[package]] -name = "quinn" -version = "0.11.6" +name = "concurrent-queue" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ - "bytes", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash 2.1.1", - "rustls 0.23.25", - "socket2 0.5.8", - "thiserror 2.0.12", - "tokio", - "tracing", + "crossbeam-utils", ] [[package]] -name = "quinn-proto" -version = "0.11.9" +name = "condtype" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf0a07a401f374238ab8e2f11a104d2851bf9ce711ec69804834de8af45c7af" + +[[package]] +name = "config" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" +checksum = "68578f196d2a33ff61b27fae256c3164f65e36382648e30666dde05b8cc9dfdf" dependencies = [ - "bytes", - "getrandom 0.2.15", - "rand 0.8.5", - "ring 0.17.8", - "rustc-hash 2.1.1", - "rustls 0.23.25", - "rustls-pki-types", - "slab", - "thiserror 2.0.12", - "tinyvec", - "tracing", - "web-time", + "async-trait", + "nom", + "pathdiff", + "serde", + "serde_json", + "yaml-rust2", ] [[package]] -name = "quinn-udp" -version = "0.5.9" +name = "console" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c40286217b4ba3a71d644d752e6a0b71f13f1b6a2c5311acfcbe0c2418ed904" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" dependencies = [ - "cfg_aliases 0.2.1", + "encode_unicode", "libc", "once_cell", - "socket2 0.5.8", - "tracing", + "unicode-width", "windows-sys 0.59.0", ] [[package]] -name = "quote" -version = "1.0.37" +name = "console-api" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "8030735ecb0d128428b64cd379809817e620a40e5001c54465b99ec5feec2857" dependencies = [ - "proc-macro2", + "futures-core", + "prost", + "prost-types", + "tonic", + "tracing-core", ] [[package]] -name = "r-efi" -version = "5.2.0" +name = "console-subscriber" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" +checksum = "6539aa9c6a4cd31f4b1c040f860a1eac9aa80e7df6b05d506a6e7179936d6a01" +dependencies = [ + "console-api", + "crossbeam-channel", + "crossbeam-utils", + "futures-task", + "hdrhistogram", + "humantime", + "hyper-util", + "prost", + "prost-types", + "serde", + "serde_json", + "thread_local", + "tokio", + "tokio-stream", + "tonic", + "tracing", + "tracing-core", + "tracing-subscriber", +] [[package]] -name = "radium" -version = "0.7.0" +name = "const-oid" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] -name = "radix_trie" -version = "0.2.1" +name = "cookie" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" dependencies = [ - "endian-type", - "nibble_vec", + "time", + "version_check", ] [[package]] -name = "rand" -version = "0.8.5" +name = "core-foundation" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ + "core-foundation-sys", "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" -dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.3", - "zerocopy 0.8.24", ] [[package]] -name = "rand_chacha" -version = "0.3.1" +name = "core-foundation-sys" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] -name = "rand_chacha" -version = "0.9.0" +name = "cpufeatures" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ - "ppv-lite86", - "rand_core 0.9.3", + "libc", ] [[package]] -name = "rand_core" -version = "0.6.4" +name = "crc32fast" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ - "getrandom 0.2.15", + "cfg-if", ] [[package]] -name = "rand_core" -version = "0.9.3" +name = "croner" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "c344b0690c1ad1c7176fe18eb173e0c927008fdaaa256e40dfd43ddd149c0843" dependencies = [ - "getrandom 0.3.2", + "chrono", ] [[package]] -name = "rand_distr" -version = "0.4.3" +name = "crossbeam-channel" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ - "num-traits", - "rand 0.8.5", + "crossbeam-utils", ] [[package]] -name = "range-alloc" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab" - -[[package]] -name = "raw-cpuid" -version = "11.2.0" +name = "crossbeam-epoch" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ab240315c661615f2ee9f0f2cd32d5a7343a84d5ebcccb99d46e6637565e7b0" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "bitflags 2.6.0", + "crossbeam-utils", ] [[package]] -name = "raw-window-handle" -version = "0.6.2" +name = "crossbeam-utils" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] -name = "rawpointer" -version = "0.2.1" +name = "crypto-common" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] [[package]] -name = "rayon" -version = "1.10.0" +name = "curve25519-dalek" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ - "either", - "rayon-core", + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "rustc_version", + "subtle", ] [[package]] -name = "rayon-core" -version = "1.12.1" +name = "curve25519-dalek-derive" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ - "crossbeam-deque", - "crossbeam-utils", + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "redis" -version = "0.23.3" -source = "git+https://github.com/rivet-gg/redis-rs?rev=ac3e27f#ac3e27fa1d133847db54354493f4d25957ad3466" +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" dependencies = [ - "arc-swap", - "async-trait", - "bytes", - "combine", - "futures", - "futures-util", - "itoa 1.0.14", - "native-tls", - "percent-encoding", - "pin-project-lite", - "ryu", - "sha1_smol", - "socket2 0.4.10", - "tokio", - "tokio-native-tls", - "tokio-retry", - "tokio-util 0.7.12", - "url", + "darling_core 0.14.4", + "darling_macro 0.14.4", ] [[package]] -name = "redis-util" -version = "25.5.2" +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ - "lazy_static", - "redis", - "regex", + "darling_core 0.20.11", + "darling_macro 0.20.11", ] [[package]] -name = "redox_syscall" -version = "0.2.16" +name = "darling_core" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" dependencies = [ - "bitflags 1.3.2", + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 1.0.109", ] [[package]] -name = "redox_syscall" -version = "0.3.5" +name = "darling_core" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ - "bitflags 1.3.2", + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.11.1", + "syn 2.0.104", ] [[package]] -name = "redox_syscall" -version = "0.5.7" +name = "darling_macro" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" dependencies = [ - "bitflags 2.6.0", + "darling_core 0.14.4", + "quote", + "syn 1.0.109", ] [[package]] -name = "redox_users" -version = "0.4.6" +name = "darling_macro" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ - "getrandom 0.2.15", - "libredox", - "thiserror 1.0.69", + "darling_core 0.20.11", + "quote", + "syn 2.0.104", ] [[package]] -name = "ref-cast" -version = "1.0.23" +name = "dashmap" +version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ - "ref-cast-impl", + "cfg-if", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", ] [[package]] -name = "ref-cast-impl" -version = "1.0.23" +name = "data-encoding" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" [[package]] -name = "regex" -version = "1.11.1" +name = "deadpool" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "5ed5957ff93768adf7a65ab167a17835c3d2c3c50d084fe305174c112f468e2f" dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.4.9", - "regex-syntax 0.8.5", + "deadpool-runtime", + "num_cpus", + "tokio", ] [[package]] -name = "regex-automata" -version = "0.1.10" +name = "deadpool-postgres" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +checksum = "3d697d376cbfa018c23eb4caab1fd1883dd9c906a8c034e8d9a3cb06a7e0bef9" dependencies = [ - "regex-syntax 0.6.29", + "async-trait", + "deadpool", + "getrandom 0.2.16", + "tokio", + "tokio-postgres", + "tracing", ] [[package]] -name = "regex-automata" -version = "0.4.9" +name = "deadpool-runtime" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b" dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.8.5", + "tokio", ] [[package]] -name = "regex-lite" -version = "0.1.6" +name = "der" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] [[package]] -name = "regex-syntax" -version = "0.6.29" +name = "deranged" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +dependencies = [ + "powerfmt", + "serde", +] [[package]] -name = "regex-syntax" -version = "0.8.5" +name = "derive_builder" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "region-get" -version = "25.5.2" +checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" dependencies = [ - "chirp-client", - "chirp-worker", - "chirp-workflow", - "cluster", - "faker-region", - "prost 0.10.4", - "rivet-operation", - "sqlx", + "derive_builder_macro 0.12.0", ] [[package]] -name = "region-list" -version = "25.5.2" +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" dependencies = [ - "chirp-client", - "chirp-worker", - "chirp-workflow", - "cluster", - "faker-region", - "prost 0.10.4", - "rivet-operation", - "sqlx", + "derive_builder_macro 0.20.2", ] [[package]] -name = "region-list-for-game" -version = "25.5.2" +name = "derive_builder_core" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" dependencies = [ - "chirp-client", - "chirp-worker", - "chirp-workflow", - "cluster", - "faker-region", - "prost 0.10.4", - "rivet-operation", - "sqlx", + "darling 0.14.4", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] -name = "region-recommend" -version = "25.5.2" +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ - "chirp-client", - "chirp-worker", - "geoutils", - "ip-info", - "prost 0.10.4", - "region-get", - "region-list", - "rivet-operation", - "sqlx", + "darling 0.20.11", + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "region-resolve" -version = "25.5.2" +name = "derive_builder_macro" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" dependencies = [ - "chirp-client", - "chirp-worker", - "chirp-workflow", - "cluster", - "faker-region", - "prost 0.10.4", - "region-get", - "region-list", - "rivet-operation", - "sqlx", + "derive_builder_core 0.12.0", + "syn 1.0.109", ] [[package]] -name = "region-resolve-for-game" -version = "25.5.2" +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ - "chirp-client", - "chirp-worker", - "chirp-workflow", - "cluster", - "faker-region", - "prost 0.10.4", - "region-get", - "region-list-for-game", - "rivet-operation", - "sqlx", + "derive_builder_core 0.20.2", + "syn 2.0.104", ] [[package]] -name = "reqwest" -version = "0.11.27" +name = "diff" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" -dependencies = [ - "base64 0.21.7", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.31", - "hyper-rustls 0.24.2", - "hyper-tls 0.5.0", - "ipnet", - "js-sys", - "log", - "mime", - "mime_guess", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls 0.21.12", - "rustls-pemfile 1.0.4", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 0.1.2", - "system-configuration 0.5.1", - "tokio", - "tokio-native-tls", - "tokio-rustls 0.24.1", - "tokio-util 0.7.12", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", - "webpki-roots 0.25.4", - "winreg", -] +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] -name = "reqwest" -version = "0.12.12" +name = "digest" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "base64 0.22.1", - "bytes", - "encoding_rs", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.4.7", - "http 1.1.0", - "http-body 1.0.1", - "http-body-util", - "hyper 1.6.0", - "hyper-rustls 0.27.3", - "hyper-tls 0.6.0", - "hyper-util", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "quinn", - "rustls 0.23.25", - "rustls-pemfile 2.2.0", - "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 1.0.2", - "system-configuration 0.6.1", - "tokio", - "tokio-native-tls", - "tokio-rustls 0.26.2", - "tokio-util 0.7.12", - "tower 0.5.2", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", - "webpki-roots 0.26.7", - "windows-registry", + "block-buffer", + "crypto-common", + "subtle", ] [[package]] -name = "resolv-conf" -version = "0.7.0" +name = "dirs" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ - "hostname", - "quick-error", + "dirs-sys", ] [[package]] -name = "rfc6979" -version = "0.3.1" +name = "dirs-next" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ - "crypto-bigint 0.4.9", - "hmac 0.12.1", - "zeroize", + "cfg-if", + "dirs-sys-next", ] [[package]] -name = "rfc6979" -version = "0.4.0" +name = "dirs-sys" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ - "hmac 0.12.1", - "subtle", + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", ] [[package]] -name = "ring" -version = "0.16.20" +name = "dirs-sys-next" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ - "cc", "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "web-sys", + "redox_users", "winapi", ] [[package]] -name = "ring" -version = "0.17.8" +name = "displaydoc" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "divan" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a405457ec78b8fe08b0e32b4a3570ab5dff6dd16eb9e76a5ee0a9d9cbd898933" dependencies = [ - "cc", "cfg-if", - "getrandom 0.2.15", + "clap", + "condtype", + "divan-macros", "libc", - "spin 0.9.8", - "untrusted 0.9.0", - "windows-sys 0.52.0", + "regex-lite", ] [[package]] -name = "ripemd" -version = "0.1.3" +name = "divan-macros" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +checksum = "9556bc800956545d6420a640173e5ba7dfa82f38d3ea5a167eb555bc69ac3323" dependencies = [ - "digest 0.10.7", + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "rivet-api" -version = "0.0.1" +name = "dyn-clone" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ - "reqwest 0.11.27", - "serde", - "serde_derive", - "serde_json", - "serde_with 2.3.3", - "url", - "uuid", + "signature", ] [[package]] -name = "rivet-auth" -version = "0.0.1" +name = "ed25519-dalek" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" dependencies = [ - "aws-smithy-client", - "aws-smithy-http 0.41.0", - "aws-smithy-json 0.41.0", - "aws-smithy-types 0.41.0", - "bytes", - "http 0.2.12", - "tower 0.4.13", + "curve25519-dalek", + "ed25519", + "sha2", + "signature", + "subtle", ] [[package]] -name = "rivet-auth-server" -version = "0.0.1" +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ - "chrono", - "serde", - "serde_json", + "cfg-if", ] [[package]] -name = "rivet-cache" -version = "25.5.2" +name = "endian-type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" + +[[package]] +name = "epoxy" +version = "0.0.1" dependencies = [ + "anyhow", + "axum 0.8.4", + "base64 0.22.1", + "bytes", + "epoxy-protocol", "futures-util", - "global-error", + "gasoline", "lazy_static", - "moka", - "prost 0.10.4", - "prost-types 0.10.1", - "rand 0.8.5", - "redis", - "rivet-cache-result", + "libc", + "portpicker", + "protobuf", + "reqwest", + "rivet-api-builder", "rivet-config", - "rivet-env", - "rivet-metrics", + "rivet-error", "rivet-pools", + "rivet-runtime", + "rivet-test-deps", "rivet-util", "serde", + "serde_bare", "serde_json", - "thiserror 1.0.69", + "sha2", + "slog", + "slog-async", + "slog-term", "tokio", "tracing", - "types-proto", + "tracing-slog", + "udb-util", + "universaldb", + "url", "uuid", + "versioned-data-util", ] [[package]] -name = "rivet-cache-result" -version = "25.5.2" +name = "epoxy-protocol" +version = "0.0.1" dependencies = [ + "anyhow", + "bare_gen", + "indoc", + "prettyplease", "rivet-util", + "serde", + "serde_bare", + "serde_json", + "syn 2.0.104", + "versioned-data-util", ] [[package]] -name = "rivet-cf-verification" -version = "0.0.1" +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ - "aws-smithy-client", - "aws-smithy-http 0.41.0", - "aws-smithy-json 0.41.0", - "aws-smithy-types 0.41.0", - "bytes", - "http 0.2.12", - "tower 0.4.13", + "libc", + "windows-sys 0.60.2", ] [[package]] -name = "rivet-cf-verification-server" -version = "0.0.1" +name = "error-code" +version = "3.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" + +[[package]] +name = "event-listener" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" dependencies = [ - "chrono", - "serde", - "serde_json", + "concurrent-queue", + "parking", + "pin-project-lite", ] [[package]] -name = "rivet-claims" -version = "25.5.2" +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "base64 0.13.1", - "global-error", - "jsonwebtoken", - "lazy_static", - "prost 0.10.4", - "rivet-util", - "serde", - "serde_json", - "thiserror 1.0.69", - "types-proto", - "uuid", + "event-listener", + "pin-project-lite", ] [[package]] -name = "rivet-cli" -version = "25.5.2" +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fd-lock" +version = "4.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" dependencies = [ - "anyhow", - "async-posthog", - "clap", - "ctrlc", - "deno-embed", - "indoc 2.0.5", - "inquire", - "kv-str", - "nix 0.30.1", - "rivet-toolchain", - "serde", - "serde_json", - "sysinfo 0.32.1", - "tempfile", - "tokio", - "url", - "uuid", - "vergen", - "webbrowser", + "cfg-if", + "rustix", + "windows-sys 0.59.0", ] [[package]] -name = "rivet-cloud" -version = "0.0.1" +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "flate2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" dependencies = [ - "aws-smithy-client", - "aws-smithy-http 0.41.0", - "aws-smithy-json 0.41.0", - "aws-smithy-types 0.41.0", - "bytes", - "http 0.2.12", - "tower 0.4.13", + "crc32fast", + "miniz_oxide", ] [[package]] -name = "rivet-cloud-server" -version = "0.0.1" +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ - "chrono", - "serde", - "serde_json", + "foreign-types-shared", ] [[package]] -name = "rivet-config" -version = "25.5.2" +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ - "config", - "dirs", - "glob", - "global-error", - "ipnet", - "json5", - "maplit", - "schemars", - "serde", - "serde_json", - "url", + "percent-encoding", +] + +[[package]] +name = "foundationdb-tuple" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1832c1fbe592de718893f7c3b48179a47757f8974d1498fece997454c2b0fa" +dependencies = [ + "memchr", "uuid", ] [[package]] -name = "rivet-connection" -version = "25.5.2" +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ - "chirp-client", - "chirp-perf", - "fdb-util", - "global-error", - "rivet-cache", - "rivet-pools", - "rivet-util", - "tracing", + "futures-core", + "futures-sink", ] [[package]] -name = "rivet-convert" -version = "25.5.2" -dependencies = [ - "cdn-namespace-get", - "chirp-client", - "chrono", - "cluster", - "game-get", - "game-namespace-get", - "game-namespace-list", - "game-resolve-namespace-id", - "game-token-development-validate", - "game-validate", - "game-version-validate", - "job-run", - "mm-lobby-player-count", - "mm-lobby-runtime-aggregate", - "mm-player-count-for-namespace", - "region-get", - "region-list-for-game", - "region-resolve", - "rivet-api", - "rivet-config", - "rivet-group-server", - "rivet-operation", - "rivet-portal-server", - "rivet-util-mm", - "serde", - "serde_json", - "team-get", - "team-member-count", - "team-profile-validate", - "team-validate", - "tier", - "types-proto", - "user-get", - "user-identity-get", - "user-team-list", -] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] -name = "rivet-edge-server" -version = "25.5.2" +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ - "anyhow", - "api-edge-monolith-edge", - "api-edge-monolith-public", - "chirp-workflow", - "clap", - "edge-monolith-workflow-worker", - "pegboard-usage-metrics-publish", - "pegboard-ws", - "rivet-cache", - "rivet-config", - "rivet-connection", - "rivet-migrate", - "rivet-runtime", - "rivet-server-cli", - "rivet-service-manager", - "s3-util", + "futures-core", + "futures-task", + "futures-util", ] [[package]] -name = "rivet-env" -version = "25.5.2" -dependencies = [ - "anyhow", - "lazy_static", - "uuid", - "vergen", -] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] -name = "rivet-group" -version = "0.0.7" +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ - "aws-smithy-client", - "aws-smithy-http 0.41.0", - "aws-smithy-json 0.41.0", - "aws-smithy-types 0.41.0", - "bytes", - "http 0.2.12", - "tower 0.4.13", + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "rivet-group-server" -version = "0.0.7" -dependencies = [ - "chrono", - "serde", - "serde_json", -] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] -name = "rivet-guard" -version = "25.5.2" +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ - "anyhow", - "chirp-client", - "chirp-workflow", - "clap", - "cluster", - "fdb-util", - "foundationdb", - "futures", - "game-namespace-resolve-name-id", - "global-error", - "once_cell", - "pegboard", - "regex", - "rivet-cache", - "rivet-config", - "rivet-connection", - "rivet-guard-core", - "rivet-logs", - "rivet-metrics", - "rivet-pools", - "rivet-runtime", - "route", - "rustls 0.23.25", - "rustls-pemfile 2.2.0", - "serde_json", - "service-discovery", - "tokio", - "tracing", - "types-proto", - "url", - "uuid", + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", ] [[package]] -name = "rivet-guard-core" -version = "25.5.2" +name = "gasoline" +version = "0.0.1" dependencies = [ - "bytes", - "chirp-workflow", - "clickhouse-inserter", - "clickhouse-user-query", - "cluster", - "futures", + "anyhow", + "async-stream", + "async-trait", + "cjson", + "dirs", "futures-util", - "global-error", - "http-body 1.0.1", - "http-body-util", - "hyper 1.6.0", - "hyper-tungstenite", - "hyper-util", + "gasoline-macros", + "hex", + "include_dir", + "itertools 0.14.0", "lazy_static", - "moka", - "once_cell", - "pegboard", - "prometheus", + "lz4_flex", + "md5", + "opentelemetry", + "papaya", + "portpicker", "rand 0.8.5", - "regex", - "reqwest 0.11.27", + "rivet-cache", "rivet-config", + "rivet-env", "rivet-metrics", - "rustls 0.23.25", - "rustls-pemfile 2.2.0", - "serde", - "serde_json", - "tokio", - "tokio-rustls 0.26.2", - "tokio-stream", - "tokio-tungstenite 0.26.2", - "tracing", - "tracing-subscriber", - "uuid", -] - -[[package]] -name = "rivet-health-checks" -version = "25.5.2" -dependencies = [ - "chirp-client", - "global-error", - "hyper 0.14.31", - "rivet-config", "rivet-pools", + "rivet-runtime", + "rivet-test-deps", + "rivet-util", "serde", "serde_json", + "statrs", + "strum", "thiserror 1.0.69", "tokio", + "tokio-util", "tracing", + "tracing-logfmt", + "tracing-opentelemetry", + "tracing-subscriber", + "udb-util", + "universaldb", + "universalpubsub", + "url", "uuid", ] [[package]] -name = "rivet-identity" -version = "0.0.14" +name = "gasoline-macros" +version = "0.0.1" dependencies = [ - "aws-smithy-client", - "aws-smithy-http 0.41.0", - "aws-smithy-json 0.41.0", - "aws-smithy-types 0.41.0", - "bytes", - "http 0.2.12", - "tower 0.4.13", + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "rivet-identity-server" -version = "0.0.14" +name = "generator" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d18470a76cb7f8ff746cf1f7470914f900252ec36bbc40b569d74b1258446827" dependencies = [ - "chrono", - "serde", - "serde_json", + "cc", + "cfg-if", + "libc", + "log", + "rustversion", + "windows 0.61.3", ] [[package]] -name = "rivet-job" -version = "0.0.1" +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ - "aws-smithy-client", - "aws-smithy-http 0.41.0", - "aws-smithy-json 0.41.0", - "aws-smithy-types 0.41.0", - "bytes", - "http 0.2.12", - "tower 0.4.13", + "typenum", + "version_check", ] [[package]] -name = "rivet-job-runner" -version = "25.5.2" +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ - "anyhow", - "portpicker", - "serde", - "serde_json", - "signal-hook", - "tempfile", - "uuid", + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] -name = "rivet-job-server" -version = "0.0.1" +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ - "chrono", - "serde", - "serde_json", + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", ] [[package]] -name = "rivet-js-utils-embed" -version = "25.5.2" -dependencies = [ - "anyhow", - "deno-embed", - "fs_extra", - "include_dir", - "merkle_hash", - "sha2 0.10.8", - "tempfile", - "tokio", - "walkdir", -] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] -name = "rivet-kv" -version = "0.0.8" -dependencies = [ - "aws-smithy-client", - "aws-smithy-http 0.41.0", - "aws-smithy-json 0.41.0", - "aws-smithy-types 0.41.0", - "bytes", - "http 0.2.12", - "tower 0.4.13", -] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] -name = "rivet-kv-server" -version = "0.0.8" +name = "governor" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68a7f542ee6b35af73b06abc0dad1c1bae89964e4e253bc4b587b91c9637867b" dependencies = [ - "chrono", - "serde", - "serde_json", + "cfg-if", + "dashmap", + "futures", + "futures-timer", + "no-std-compat", + "nonzero_ext", + "parking_lot", + "portable-atomic", + "quanta", + "rand 0.8.5", + "smallvec", + "spinning_top", ] [[package]] -name = "rivet-logs" -version = "0.0.1" +name = "h2" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" dependencies = [ - "anyhow", - "chrono", - "nix 0.30.1", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap 2.10.0", + "slab", "tokio", + "tokio-util", "tracing", - "tracing-logfmt", - "tracing-subscriber", ] [[package]] -name = "rivet-matchmaker" -version = "0.0.8" +name = "h2" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785" dependencies = [ - "aws-smithy-client", - "aws-smithy-http 0.41.0", - "aws-smithy-json 0.41.0", - "aws-smithy-types 0.41.0", + "atomic-waker", "bytes", - "http 0.2.12", - "tower 0.4.13", + "fnv", + "futures-core", + "futures-sink", + "http 1.3.1", + "indexmap 2.10.0", + "slab", + "tokio", + "tokio-util", + "tracing", ] [[package]] -name = "rivet-matchmaker-server" -version = "0.0.8" -dependencies = [ - "chrono", - "serde", - "serde_json", -] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] -name = "rivet-metrics" -version = "25.5.2" +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "global-error", - "hyper 0.14.31", - "lazy_static", - "prometheus", - "rivet-config", - "rivet-env", - "tokio", - "tracing", + "ahash", + "allocator-api2", ] [[package]] -name = "rivet-migrate" -version = "25.5.2" -dependencies = [ - "anyhow", - "futures-util", - "include_dir", - "indoc 1.0.9", - "rivet-config", - "rivet-pools", - "rivet-util", - "tempfile", - "tokio", - "tracing", - "url", - "urlencoding", -] +name = "hashbrown" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" [[package]] -name = "rivet-operation" -version = "25.5.2" +name = "hashlink" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ - "async-trait", - "chirp-client", - "chirp-metrics", - "chirp-perf", - "formatted-error", - "futures-util", - "global-error", - "indoc 1.0.9", - "prost 0.10.4", - "prost-types 0.10.1", - "rivet-cache", - "rivet-config", - "rivet-connection", - "rivet-operation-macros", - "rivet-pools", - "rivet-util", - "serde_json", - "thiserror 1.0.69", - "tokio", - "tracing", - "types-proto", + "hashbrown 0.14.5", ] [[package]] -name = "rivet-operation-macros" -version = "25.5.2" +name = "hdrhistogram" +version = "7.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", + "base64 0.21.7", + "byteorder", + "flate2", + "nom", + "num-traits", ] [[package]] -name = "rivet-party" -version = "0.0.7" +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" dependencies = [ - "aws-smithy-client", - "aws-smithy-http 0.41.0", - "aws-smithy-json 0.41.0", - "aws-smithy-types 0.41.0", - "bytes", - "http 0.2.12", - "tower 0.4.13", + "unicode-segmentation", ] [[package]] -name = "rivet-party-server" -version = "0.0.7" +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "chrono", - "serde", - "serde_json", + "digest", ] [[package]] -name = "rivet-pools" -version = "25.5.2" +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ - "anyhow", - "async-nats", - "clickhouse", - "clickhouse-inserter", - "dirs", - "divan", - "fdb-util", - "foundationdb", - "funty 1.1.0", - "futures-util", - "global-error", - "governor", - "hex", - "hyper 0.14.31", - "hyper-tls 0.5.0", - "lazy_static", - "lz4_flex", - "papaya", - "redis", - "reqwest 0.11.27", - "rivet-config", - "rivet-metrics", - "rivet-util", - "service-discovery", - "sqlx", - "tempfile", - "thiserror 1.0.69", - "tokio", - "tokio-native-tls", - "tokio-util 0.7.12", - "tracing", - "tracing-logfmt", - "tracing-subscriber", - "url", - "uuid", + "windows-sys 0.59.0", ] [[package]] -name = "rivet-portal" -version = "0.0.1" +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ - "aws-smithy-client", - "aws-smithy-http 0.41.0", - "aws-smithy-json 0.41.0", - "aws-smithy-types 0.41.0", "bytes", - "http 0.2.12", - "tower 0.4.13", + "fnv", + "itoa 1.0.15", ] [[package]] -name = "rivet-portal-server" -version = "0.0.1" +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ - "chrono", - "serde", - "serde_json", + "bytes", + "fnv", + "itoa 1.0.15", ] [[package]] -name = "rivet-route" -version = "0.0.1" +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ - "aws-smithy-client", - "aws-smithy-http 0.41.0", - "aws-smithy-json 0.41.0", - "aws-smithy-types 0.41.0", "bytes", "http 0.2.12", - "tower 0.4.13", + "pin-project-lite", ] [[package]] -name = "rivet-runtime" -version = "25.5.2" +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ - "console-subscriber", - "lazy_static", - "opentelemetry 0.28.0", - "opentelemetry-appender-tracing", - "opentelemetry-otlp 0.28.0", - "opentelemetry-semantic-conventions 0.28.0", - "opentelemetry-stdout", - "opentelemetry_sdk 0.28.0", - "reqwest 0.12.12", - "rivet-env", - "rivet-metrics", - "serde", - "serde_json", - "thiserror 1.0.69", - "tokio", - "tracing", - "tracing-core", - "tracing-logfmt", - "tracing-opentelemetry", - "tracing-subscriber", + "bytes", + "http 1.3.1", ] [[package]] -name = "rivet-schema-generator" -version = "25.5.2" +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ - "anyhow", - "pegboard-config", - "rivet-config", - "rivet-toolchain", - "schemars", - "serde_json", + "bytes", + "futures-core", + "http 1.3.1", + "http-body 1.0.1", + "pin-project-lite", ] [[package]] -name = "rivet-server" -version = "25.5.2" -dependencies = [ - "anyhow", - "api-core-monolith-edge", - "api-core-monolith-public", - "build-default-create", - "chirp-client", - "chirp-workflow", - "clap", - "cloud-default-create", - "cluster-datacenter-tls-renew", - "cluster-default-update", - "cluster-gc", - "cluster-metrics-publish", - "include_dir", - "job-gc", - "linode-gc", - "load-test-api-cloud", - "load-test-mm", - "load-test-mm-sustain", - "load-test-sqlx", - "load-test-watch-requests", - "mm-gc", - "monolith-worker", - "monolith-workflow-worker", - "nomad-monitor", - "rivet-cache", - "rivet-config", - "rivet-connection", - "rivet-migrate", - "rivet-runtime", - "rivet-server-cli", - "rivet-service-manager", - "s3-util", - "telemetry-beacon", - "user-delete-pending", -] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] -name = "rivet-server-cli" -version = "25.5.2" -dependencies = [ - "anyhow", - "chirp-workflow", - "chrono", - "clap", - "colored_json", - "fdb-util", - "foundationdb", - "futures-util", - "global-error", - "hex", - "include_dir", - "indoc 2.0.5", - "lz4_flex", - "reqwest 0.12.12", - "rivet-api", - "rivet-config", - "rivet-logs", - "rivet-migrate", - "rivet-pools", - "rivet-runtime", - "rivet-service-manager", - "rivet-term", - "rustyline 15.0.0", - "s3-util", - "serde", - "serde_json", - "serde_yaml", - "sqlx", - "strum 0.26.3", - "tabled", - "tempfile", - "thiserror 1.0.69", - "tokio", - "tracing", - "url", - "uuid", -] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] -name = "rivet-service-manager" -version = "25.5.2" -dependencies = [ - "anyhow", - "chrono", - "global-error", - "include_dir", - "rivet-config", - "rivet-health-checks", - "rivet-metrics", - "rivet-migrate", - "rivet-pools", - "s3-util", - "tokio", - "tokio-cron-scheduler", - "tracing", -] +name = "humantime" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" [[package]] -name = "rivet-status" -version = "0.0.1" +name = "hyper" +version = "0.14.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ - "aws-smithy-client", - "aws-smithy-http 0.41.0", - "aws-smithy-json 0.41.0", - "aws-smithy-types 0.41.0", "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.3.27", "http 0.2.12", - "tower 0.4.13", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa 1.0.15", + "pin-project-lite", + "socket2 0.5.10", + "tokio", + "tower-service", + "tracing", + "want", ] [[package]] -name = "rivet-status-server" -version = "0.0.1" +name = "hyper" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" dependencies = [ - "chrono", - "serde", - "serde_json", + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.11", + "http 1.3.1", + "http-body 1.0.1", + "httparse", + "httpdate", + "itoa 1.0.15", + "pin-project-lite", + "smallvec", + "tokio", + "want", ] [[package]] -name = "rivet-term" -version = "0.1.0" -source = "git+https://github.com/rivet-gg/rivet-term?rev=55e328470b68c557fb9bc8298369f90182d35b6d#55e328470b68c557fb9bc8298369f90182d35b6d" +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "console", - "derive_builder 0.12.0", - "tabled", - "term_size", - "thiserror 1.0.69", + "http 1.3.1", + "hyper 1.6.0", + "hyper-util", + "rustls 0.23.29", + "rustls-pki-types", "tokio", + "tokio-rustls 0.26.2", + "tower-service", ] [[package]] -name = "rivet-test" -version = "25.5.2" +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "types-proto", + "hyper 1.6.0", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", ] [[package]] -name = "rivet-test-images" -version = "25.5.2" +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ - "testcontainers 0.12.0", + "bytes", + "hyper 0.14.32", + "native-tls", + "tokio", + "tokio-native-tls", ] [[package]] -name = "rivet-toolchain" -version = "25.5.2" +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ - "anyhow", - "assert_cmd", - "async-stream", - "base64 0.22.1", - "chrono", - "clap", - "console", - "const_format", - "deno-embed", - "dirs", - "flate2", - "futures-util", - "humansize", - "ignore", - "include_dir", - "indicatif", - "jsonc-parser", - "kv-str", - "lazy_static", - "lz4", - "mime_guess", - "pkg-version", - "regex", - "reqwest 0.11.27", - "rivet-api", - "rivet-js-utils-embed", - "schemars", - "serde", - "serde_json", - "sha1", - "strip-ansi-escapes", - "strum 0.24.1", - "tar", - "tempfile", + "bytes", + "http-body-util", + "hyper 1.6.0", + "hyper-util", + "native-tls", "tokio", - "tokio-util 0.7.12", - "typed-path", - "url", - "uuid", - "vergen", - "which 5.0.0", - "windows 0.48.0", - "zip", + "tokio-native-tls", + "tower-service", ] [[package]] -name = "rivet-traefik-provider-server" -version = "0.0.1" +name = "hyper-tungstenite" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0110a0487cbc65c3d1f38c2ef851dbf8bee8c2761e5a96be6a59ba84412b4752" dependencies = [ - "chrono", - "serde", - "serde_json", + "http-body-util", + "hyper 1.6.0", + "hyper-util", + "pin-project-lite", + "tokio", + "tokio-tungstenite", + "tungstenite", ] [[package]] -name = "rivet-util" -version = "25.5.2" +name = "hyper-util" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" dependencies = [ - "async-trait", - "bcrypt", - "chrono", - "formatted-error", + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-core", "futures-util", - "global-error", - "indexmap 2.7.0", + "http 1.3.1", + "http-body 1.0.1", + "hyper 1.6.0", "ipnet", - "lazy_static", - "rand 0.8.5", - "regex", - "reqwest 0.12.12", - "rivet-config", - "rivet-metrics", - "rivet-util-macros", - "serde", - "serde_json", - "sqlx", - "thiserror 1.0.69", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2 0.6.0", + "system-configuration", "tokio", + "tower-service", "tracing", - "types-proto", - "url", - "uuid", + "windows-registry", ] [[package]] -name = "rivet-util-build" -version = "25.5.2" +name = "iana-time-zone" +version = "0.1.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" dependencies = [ - "rivet-operation", + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core 0.61.2", ] [[package]] -name = "rivet-util-captcha" -version = "25.5.2" +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ - "global-error", - "serde_json", + "cc", ] [[package]] -name = "rivet-util-cdn" -version = "25.5.2" +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] [[package]] -name = "rivet-util-job" -version = "25.5.2" +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" dependencies = [ - "uuid", + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", ] [[package]] -name = "rivet-util-macros" -version = "25.5.2" +name = "icu_normalizer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", ] [[package]] -name = "rivet-util-mm" -version = "25.5.2" +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" dependencies = [ - "bit-vec", - "chirp-client", - "heck 0.3.3", - "http 0.2.12", - "ip-info", - "mm-lobby-list-for-user-id", - "region-get", - "rivet-operation", - "rivet-util", - "serde", - "serde_json", - "strum 0.24.1", - "user-identity-get", - "uuid", + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", ] [[package]] -name = "rivet-util-search" -version = "25.5.2" +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" dependencies = [ - "uuid", + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", ] [[package]] -name = "rivet-util-team" -version = "25.5.2" +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "rivet-operation", + "idna_adapter", + "smallvec", + "utf8_iter", ] [[package]] -name = "ron" -version = "0.8.1" +name = "idna_adapter" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ - "base64 0.21.7", - "bitflags 2.6.0", - "serde", - "serde_derive", + "icu_normalizer", + "icu_properties", ] [[package]] -name = "route" -version = "25.5.2" +name = "include_dir" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd" dependencies = [ - "chirp-client", - "chirp-workflow", - "futures-util", - "rivet-api", - "rivet-convert", - "rivet-operation", - "rivet-util", - "serde", - "serde_json", - "sqlx", - "strum 0.24.1", - "uuid", + "include_dir_macros", ] [[package]] -name = "rsa" -version = "0.9.7" +name = "include_dir_macros" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519" +checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75" dependencies = [ - "const-oid", - "digest 0.10.7", - "num-bigint-dig", - "num-integer", - "num-traits", - "pkcs1", - "pkcs8 0.10.2", - "rand_core 0.6.4", - "sha2 0.10.8", - "signature 2.2.0", - "spki 0.7.3", - "subtle", - "zeroize", + "proc-macro2", + "quote", ] [[package]] -name = "rusqlite" -version = "0.32.1" +name = "indexmap" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7753b721174eb8ff87a9a0e799e2d7bc3749323e773db92e0984debb00019d6e" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ - "bitflags 2.6.0", - "fallible-iterator", - "fallible-streaming-iterator", - "hashlink 0.9.1", - "libsqlite3-sys", - "smallvec", + "autocfg", + "hashbrown 0.12.3", + "serde", ] [[package]] -name = "rustc-demangle" -version = "0.1.24" +name = "indexmap" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +dependencies = [ + "equivalent", + "hashbrown 0.15.4", + "serde", +] [[package]] -name = "rustc-hash" -version = "1.1.0" +name = "indoc" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" [[package]] -name = "rustc-hash" -version = "2.1.1" +name = "inout" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] [[package]] -name = "rustc_version" -version = "0.2.3" +name = "io-uring" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" dependencies = [ - "semver 0.9.0", + "bitflags", + "cfg-if", + "libc", ] [[package]] -name = "rustc_version" -version = "0.4.1" +name = "ipnet" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" dependencies = [ - "semver 1.0.23", + "serde", ] [[package]] -name = "rusticata-macros" -version = "4.1.0" +name = "iri-string" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" dependencies = [ - "nom 7.1.3", + "memchr", + "serde", ] [[package]] -name = "rustix" -version = "0.38.41" +name = "is-terminal" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ - "bitflags 2.6.0", - "errno 0.3.10", + "hermit-abi", "libc", - "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] -name = "rustls" -version = "0.19.1" +name = "is_terminal_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" -dependencies = [ - "base64 0.13.1", - "log", - "ring 0.16.20", - "sct 0.6.1", - "webpki 0.21.4", -] +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] -name = "rustls" -version = "0.21.12" +name = "itertools" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ - "log", - "ring 0.17.8", - "rustls-webpki 0.101.7", - "sct 0.7.1", + "either", ] [[package]] -name = "rustls" -version = "0.23.25" +name = "itertools" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ - "aws-lc-rs", - "log", - "once_cell", - "ring 0.17.8", - "rustls-pki-types", - "rustls-webpki 0.103.1", - "subtle", - "zeroize", + "either", ] [[package]] -name = "rustls-native-certs" -version = "0.5.0" +name = "itoa" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a07b7c1885bd8ed3831c289b7870b13ef46fe0e856d288c30d9cc17d75a2092" -dependencies = [ - "openssl-probe", - "rustls 0.19.1", - "schannel", - "security-framework 2.11.1", -] +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] -name = "rustls-native-certs" -version = "0.6.3" +name = "itoa" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" -dependencies = [ - "openssl-probe", - "rustls-pemfile 1.0.4", - "schannel", - "security-framework 2.11.1", -] +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] -name = "rustls-native-certs" -version = "0.7.3" +name = "jobserver" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ - "openssl-probe", - "rustls-pemfile 2.2.0", - "rustls-pki-types", - "schannel", - "security-framework 2.11.1", + "getrandom 0.3.3", + "libc", ] [[package]] -name = "rustls-native-certs" -version = "0.8.1" +name = "js-sys" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ - "openssl-probe", - "rustls-pki-types", - "schannel", - "security-framework 3.2.0", + "once_cell", + "wasm-bindgen", ] [[package]] -name = "rustls-pemfile" -version = "1.0.4" +name = "json5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" dependencies = [ - "base64 0.21.7", + "pest", + "pest_derive", + "serde", ] [[package]] -name = "rustls-pemfile" -version = "2.2.0" +name = "lazy_static" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] -name = "rustls-pki-types" -version = "1.11.0" +name = "libc" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" -dependencies = [ - "web-time", -] +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] -name = "rustls-tokio-stream" -version = "0.3.0" +name = "libloading" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22557157d7395bc30727745b365d923f1ecc230c4c80b176545f3f4f08c46e33" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ - "futures", - "rustls 0.23.25", - "socket2 0.5.8", - "tokio", + "cfg-if", + "windows-targets 0.53.2", ] [[package]] -name = "rustls-webpki" -version = "0.101.7" +name = "libm" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "libredox" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4488594b9328dee448adb906d8b126d9b7deb7cf5c22161ee591610bb1be83c0" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "bitflags", + "libc", ] [[package]] -name = "rustls-webpki" -version = "0.102.8" +name = "librocksdb-sys" +version = "0.17.3+10.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +checksum = "cef2a00ee60fe526157c9023edab23943fae1ce2ab6f4abb2a807c1746835de9" dependencies = [ - "ring 0.17.8", - "rustls-pki-types", - "untrusted 0.9.0", + "bindgen", + "bzip2-sys", + "cc", + "libc", + "libz-sys", + "lz4-sys", + "zstd-sys", ] [[package]] -name = "rustls-webpki" -version = "0.103.1" +name = "libz-sys" +version = "1.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" +checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" dependencies = [ - "aws-lc-rs", - "ring 0.17.8", - "rustls-pki-types", - "untrusted 0.9.0", + "cc", + "pkg-config", + "vcpkg", ] [[package]] -name = "rustversion" -version = "1.0.19" +name = "linux-raw-sys" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] -name = "rustyline" -version = "13.0.0" +name = "litemap" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02a2d683a4ac90aeef5b1013933f6d977bd37d51ff3f4dad829d4931a7e6be86" -dependencies = [ - "bitflags 2.6.0", - "cfg-if", - "clipboard-win", - "fd-lock", - "home", - "libc", - "log", - "memchr", - "nix 0.27.1", - "radix_trie", - "unicode-segmentation", - "unicode-width 0.1.14", - "utf8parse", - "winapi", -] +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] -name = "rustyline" -version = "15.0.0" +name = "lock_api" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ee1e066dc922e513bda599c6ccb5f3bb2b0ea5870a579448f2622993f0a9a2f" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ - "bitflags 2.6.0", - "cfg-if", - "clipboard-win", - "fd-lock", - "home", - "libc", - "log", - "memchr", - "nix 0.29.0", - "radix_trie", - "unicode-segmentation", - "unicode-width 0.2.0", - "utf8parse", - "windows-sys 0.59.0", + "autocfg", + "scopeguard", ] [[package]] -name = "ryu" -version = "1.0.18" +name = "log" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] -name = "ryu-js" -version = "1.0.1" +name = "loom" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad97d4ce1560a5e27cec89519dc8300d1aa6035b099821261c651486a19e44d5" - -[[package]] -name = "s3-util" -version = "25.5.2" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" dependencies = [ - "aws-sdk-s3", - "aws-smithy-async 1.2.1", - "aws-smithy-http 0.60.11", - "aws-smithy-types 1.2.9", - "global-error", - "http 0.2.12", - "rivet-config", - "rivet-util", - "thiserror 1.0.69", - "tokio", + "cfg-if", + "generator", + "scoped-tls", "tracing", + "tracing-subscriber", ] [[package]] -name = "safe_arch" -version = "0.7.4" +name = "lz4" +version = "1.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" +checksum = "a20b523e860d03443e98350ceaac5e71c6ba89aea7d960769ec3ce37f4de5af4" dependencies = [ - "bytemuck", + "lz4-sys", ] [[package]] -name = "saffron" -version = "0.1.0" +name = "lz4-sys" +version = "1.11.1+lz4-1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03fb9a628596fc7590eb7edbf7b0613287be78df107f5f97b118aad59fb2eea9" +checksum = "6bd8c0d6c6ed0cd30b3652886bb8711dc4bb01d637a68105a3d5158039b418e6" dependencies = [ - "chrono", - "nom 5.1.3", + "cc", + "libc", ] [[package]] -name = "salsa20" -version = "0.10.2" +name = "lz4_flex" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +checksum = "08ab2867e3eeeca90e844d1940eab391c9dc5228783db2ed999acbc0a9ed375a" dependencies = [ - "cipher", + "twox-hash", ] [[package]] -name = "same-file" -version = "1.0.6" +name = "maplit" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] -name = "schannel" -version = "0.1.27" +name = "matchers" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ - "windows-sys 0.59.0", + "regex-automata 0.1.10", ] [[package]] -name = "schemac" -version = "25.5.2" +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + +[[package]] +name = "matchit" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" + +[[package]] +name = "matrixmultiply" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08" dependencies = [ - "lazy_static", - "prost-build 0.11.9", - "regex", - "tempfile", + "autocfg", + "rawpointer", ] [[package]] -name = "schemars" -version = "0.8.21" +name = "md-5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ - "dyn-clone", - "schemars_derive", - "serde", - "serde_json", - "url", - "uuid", + "cfg-if", + "digest", ] [[package]] -name = "schemars_derive" -version = "0.8.21" +name = "md5" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals 0.29.1", - "syn 2.0.90", -] +checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" [[package]] -name = "scoped-tls" -version = "1.0.1" +name = "memchr" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] -name = "scopeguard" -version = "1.2.0" +name = "mime" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] -name = "scrypt" -version = "0.11.0" +name = "mime_guess" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ - "password-hash", - "pbkdf2", - "salsa20", - "sha2 0.10.8", + "mime", + "unicase", ] [[package]] -name = "sct" -version = "0.6.1" +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", + "adler2", ] [[package]] -name = "sct" -version = "0.7.1" +name = "mio" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", ] [[package]] -name = "sealed" -version = "0.4.0" +name = "moka" +version = "0.12.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b5e421024b5e5edfbaa8e60ecf90bda9dbffc602dbb230e6028763f85f0c68c" +checksum = "a9321642ca94a4282428e6ea4af8cc2ca4eac48ac7a6a4ea8f33f76d0ce70926" dependencies = [ - "heck 0.3.3", - "proc-macro2", - "quote", - "syn 1.0.109", + "async-lock", + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils", + "event-listener", + "futures-util", + "loom", + "parking_lot", + "portable-atomic", + "rustc_version", + "smallvec", + "tagptr", + "thiserror 1.0.69", + "uuid", ] [[package]] -name = "sec1" -version = "0.3.0" +name = "nalgebra" +version = "0.33.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +checksum = "26aecdf64b707efd1310e3544d709c5c0ac61c13756046aaaba41be5c4f66a3b" dependencies = [ - "base16ct 0.1.1", - "der 0.6.1", - "generic-array", - "pkcs8 0.9.0", - "subtle", - "zeroize", + "approx", + "matrixmultiply", + "num-complex", + "num-rational", + "num-traits", + "rand 0.8.5", + "rand_distr", + "simba", + "typenum", ] [[package]] -name = "sec1" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +name = "namespace" +version = "0.0.1" dependencies = [ - "base16ct 0.2.0", - "der 0.7.9", - "generic-array", - "pkcs8 0.10.2", - "serdect", - "subtle", - "zeroize", + "anyhow", + "gasoline", + "rivet-api-builder", + "rivet-api-util", + "rivet-error", + "rivet-util", + "serde", + "tracing", + "udb-util", + "universaldb", + "utoipa", ] [[package]] -name = "security-framework" -version = "2.11.1" +name = "native-tls" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" dependencies = [ - "bitflags 2.6.0", - "core-foundation 0.9.4", - "core-foundation-sys", "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", "security-framework-sys", + "tempfile", ] [[package]] -name = "security-framework" -version = "3.2.0" +name = "nibble_vec" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" dependencies = [ - "bitflags 2.6.0", - "core-foundation 0.10.0", - "core-foundation-sys", - "libc", - "security-framework-sys", + "smallvec", ] [[package]] -name = "security-framework-sys" -version = "2.14.0" +name = "nix" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "core-foundation-sys", + "bitflags", + "cfg-if", + "cfg_aliases", "libc", ] [[package]] -name = "seize" -version = "0.5.0" +name = "nix" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4b8d813387d566f627f3ea1b914c068aac94c40ae27ec43f5f33bde65abefe7" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", "libc", - "windows-sys 0.52.0", ] [[package]] -name = "semver" -version = "0.9.0" +name = "nkeys" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +checksum = "aad178aad32087b19042ee36dfd450b73f5f934fbfb058b59b198684dfec4c47" dependencies = [ - "semver-parser", + "byteorder", + "data-encoding", + "ed25519", + "ed25519-dalek", + "getrandom 0.2.16", + "log", + "rand 0.8.5", + "signatory", ] [[package]] -name = "semver" -version = "1.0.23" +name = "no-std-compat" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" + +[[package]] +name = "nom" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ - "serde", + "memchr", + "minimal-lexical", ] [[package]] -name = "semver-parser" -version = "0.7.0" +name = "nonzero_ext" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" [[package]] -name = "serde" -version = "1.0.219" +name = "nu-ansi-term" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ - "serde_derive", + "overload", + "winapi", ] [[package]] -name = "serde-value" -version = "0.7.0" +name = "nu-ansi-term" +version = "0.50.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" dependencies = [ - "ordered-float", - "serde", + "windows-sys 0.52.0", ] [[package]] -name = "serde_array_query" -version = "0.2.0" -source = "git+https://github.com/rivet-gg/serde_array_query?rev=b9f8bfa#b9f8bfad77aea6f01dccc6cb77146b8c5daecaa3" +name = "nuid" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc895af95856f929163a0aa20c26a78d26bfdc839f51b9d5aa7a5b79e52b7e83" dependencies = [ - "serde", - "serde_urlencoded", + "rand 0.8.5", ] [[package]] -name = "serde_bytes" -version = "0.11.15" +name = "num-bigint" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "serde", + "num-integer", + "num-traits", ] [[package]] -name = "serde_derive" -version = "1.0.219" +name = "num-complex" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", + "num-traits", ] [[package]] -name = "serde_derive_internals" -version = "0.26.0" +name = "num-conv" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] -name = "serde_derive_internals" -version = "0.29.1" +name = "num-derive" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.104", ] [[package]] -name = "serde_json" -version = "1.0.140" +name = "num-integer" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "indexmap 2.7.0", - "itoa 1.0.14", - "memchr", - "ryu", - "serde", + "num-traits", ] [[package]] -name = "serde_nanos" -version = "0.1.4" +name = "num-rational" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a93142f0367a4cc53ae0fead1bcda39e85beccfad3dcd717656cacab94b12985" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "serde", + "num-bigint", + "num-integer", + "num-traits", ] [[package]] -name = "serde_repr" -version = "0.1.19" +name = "num-traits" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", ] [[package]] -name = "serde_spanned" -version = "0.6.8" +name = "num_cpus" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ - "serde", + "hermit-abi", + "libc", ] [[package]] -name = "serde_urlencoded" -version = "0.7.1" +name = "object" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ - "form_urlencoded", - "itoa 1.0.14", - "ryu", - "serde", + "memchr", ] [[package]] -name = "serde_v8" -version = "0.232.0" -source = "git+https://github.com/rivet-gg/deno_core?rev=8a313913fa73d58f4f9532565b0084e723bc34ad#8a313913fa73d58f4f9532565b0084e723bc34ad" -dependencies = [ - "num-bigint", - "serde", - "smallvec", - "thiserror 1.0.69", - "v8", -] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] -name = "serde_with" -version = "2.3.3" +name = "once_cell_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" -dependencies = [ - "base64 0.13.1", - "chrono", - "hex", - "indexmap 1.9.3", - "serde", - "serde_json", - "serde_with_macros 2.3.3", - "time 0.3.37", -] +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" [[package]] -name = "serde_with" -version = "3.12.0" +name = "openssl" +version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" +checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ - "base64 0.22.1", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.7.0", - "serde", - "serde_derive", - "serde_json", - "serde_with_macros 3.12.0", - "time 0.3.37", + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", ] [[package]] -name = "serde_with_macros" -version = "2.3.3" +name = "openssl-macros" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.104", ] [[package]] -name = "serde_with_macros" -version = "3.12.0" +name = "openssl-probe" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-sys" +version = "0.9.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" dependencies = [ - "darling 0.20.10", - "proc-macro2", - "quote", - "syn 2.0.90", + "cc", + "libc", + "pkg-config", + "vcpkg", ] [[package]] -name = "serde_yaml" -version = "0.9.34+deprecated" +name = "opentelemetry" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +checksum = "236e667b670a5cdf90c258f5a55794ec5ac5027e960c224bff8367a59e1e6426" dependencies = [ - "indexmap 2.7.0", - "itoa 1.0.14", - "ryu", - "serde", - "unsafe-libyaml", + "futures-core", + "futures-sink", + "js-sys", + "pin-project-lite", + "thiserror 2.0.12", + "tracing", ] [[package]] -name = "serdect" -version = "0.2.0" +name = "opentelemetry-appender-tracing" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +checksum = "c513c7af3bec30113f3d4620134ff923295f1e9c580fda2b8abe0831f925ddc0" dependencies = [ - "base16ct 0.2.0", - "serde", + "opentelemetry", + "tracing", + "tracing-core", + "tracing-subscriber", ] [[package]] -name = "server-spec" -version = "25.5.2" +name = "opentelemetry-http" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8863faf2910030d139fb48715ad5ff2f35029fc5f244f6d5f689ddcf4d26253" dependencies = [ - "chirp-workflow", - "linode", - "rivet-config", + "async-trait", + "bytes", + "http 1.3.1", + "opentelemetry", + "reqwest", + "tracing", ] [[package]] -name = "service-discovery" -version = "25.5.2" +name = "opentelemetry-otlp" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bef114c6d41bea83d6dc60eb41720eedd0261a67af57b66dd2b84ac46c01d91" dependencies = [ - "rand 0.8.5", - "reqwest 0.12.12", - "rivet-api", - "serde", + "async-trait", + "futures-core", + "http 1.3.1", + "opentelemetry", + "opentelemetry-http", + "opentelemetry-proto", + "opentelemetry_sdk", + "prost", + "reqwest", + "thiserror 2.0.12", "tokio", + "tonic", "tracing", - "url", ] [[package]] -name = "sha1" -version = "0.10.6" +name = "opentelemetry-proto" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +checksum = "56f8870d3024727e99212eb3bb1762ec16e255e3e6f58eeb3dc8db1aa226746d" dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", + "opentelemetry", + "opentelemetry_sdk", + "prost", + "tonic", ] [[package]] -name = "sha1_smol" -version = "1.0.1" +name = "opentelemetry-semantic-conventions" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" +checksum = "2fb3a2f78c2d55362cd6c313b8abedfbc0142ab3c2676822068fd2ab7d51f9b7" [[package]] -name = "sha2" -version = "0.9.9" +name = "opentelemetry-stdout" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +checksum = "5eb0e5a5132e4b80bf037a78e3e12c8402535199f5de490d0c38f7eac71bc831" dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", + "async-trait", + "chrono", + "futures-util", + "opentelemetry", + "opentelemetry_sdk", + "serde", + "thiserror 2.0.12", ] [[package]] -name = "sha2" -version = "0.10.8" +name = "opentelemetry_sdk" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "84dfad6042089c7fc1f6118b7040dc2eb4ab520abbf410b79dc481032af39570" dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", + "async-trait", + "futures-channel", + "futures-executor", + "futures-util", + "glob", + "opentelemetry", + "percent-encoding", + "rand 0.8.5", + "serde_json", + "thiserror 2.0.12", + "tracing", ] [[package]] -name = "sha3" -version = "0.10.8" +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "papaya" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +checksum = "f92dd0b07c53a0a0c764db2ace8c541dc47320dad97c2200c2a637ab9dd2328f" dependencies = [ - "digest 0.10.7", - "keccak", + "equivalent", + "seize", ] [[package]] -name = "sharded-slab" -version = "0.1.7" +name = "papergrid" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +checksum = "d2b0f8def1f117e13c895f3eda65a7b5650688da29d6ad04635f61bc7b92eebd" dependencies = [ - "lazy_static", + "ansi-str", + "ansitok", + "bytecount", + "fnv", + "unicode-width", ] [[package]] -name = "shlex" -version = "1.3.0" +name = "parking" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] -name = "signal-hook" -version = "0.3.17" +name = "parking_lot" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ - "libc", - "signal-hook-registry", + "lock_api", + "parking_lot_core", ] [[package]] -name = "signal-hook-mio" -version = "0.2.4" +name = "parking_lot_core" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ + "cfg-if", "libc", - "mio 0.8.11", - "signal-hook", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", ] [[package]] -name = "signal-hook-registry" -version = "1.4.2" +name = "paste" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] -name = "signatory" -version = "0.27.1" +name = "pathdiff" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e303f8205714074f6068773f0e29527e0453937fe837c9717d066635b65f31" -dependencies = [ - "pkcs8 0.10.2", - "rand_core 0.6.4", - "signature 2.2.0", - "zeroize", -] +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" [[package]] -name = "signature" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +name = "pegboard" +version = "0.0.1" dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", + "anyhow", + "epoxy", + "gasoline", + "lazy_static", + "namespace", + "nix 0.30.1", + "rivet-api-client", + "rivet-api-types", + "rivet-api-util", + "rivet-error", + "rivet-key-data", + "rivet-metrics", + "rivet-runner-protocol", + "rivet-types", + "rivet-util", + "serde", + "serde_json", + "strum", + "tracing", + "udb-util", + "universaldb", + "utoipa", + "versioned-data-util", ] [[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +name = "pegboard-actor-kv" +version = "0.0.1" dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", + "anyhow", + "futures-util", + "pegboard", + "rivet-runner-protocol", + "rivet-util-id", + "serde", + "serde_bare", + "tokio", + "tracing", + "tracing-logfmt", + "tracing-subscriber", + "udb-util", + "universaldb", ] [[package]] -name = "simba" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa" +name = "pegboard-gateway" +version = "0.0.1" dependencies = [ - "approx", - "num-complex", - "num-traits", - "paste", - "wide", + "anyhow", + "async-trait", + "bytes", + "futures-util", + "gasoline", + "http-body-util", + "hyper 1.6.0", + "hyper-tungstenite", + "pegboard", + "rand 0.8.5", + "rivet-error", + "rivet-guard-core", + "rivet-tunnel-protocol", + "rivet-util", + "tokio", + "tokio-tungstenite", + "universalpubsub", ] [[package]] -name = "simd-abstraction" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cadb29c57caadc51ff8346233b5cec1d240b68ce55cf1afc764818791876987" +name = "pegboard-runner-ws" +version = "0.0.1" dependencies = [ - "outref 0.1.0", + "anyhow", + "gasoline", + "hyper 1.6.0", + "namespace", + "pegboard", + "pegboard-actor-kv", + "rivet-config", + "rivet-error", + "rivet-metrics", + "rivet-runner-protocol", + "rivet-runtime", + "serde", + "serde_json", + "tokio-tungstenite", + "tracing", + "url", + "versioned-data-util", ] [[package]] -name = "simd-adler32" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" - -[[package]] -name = "simd-json" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2bcf6c6e164e81bc7a5d49fc6988b3d515d9e8c07457d7b74ffb9324b9cd40" +name = "pegboard-tunnel" +version = "0.0.1" dependencies = [ - "getrandom 0.2.15", - "halfbrown", - "ref-cast", + "anyhow", + "async-trait", + "futures", + "gasoline", + "http-body-util", + "hyper 1.6.0", + "hyper-tungstenite", + "pegboard", + "rand 0.8.5", + "rivet-cache", + "rivet-config", + "rivet-error", + "rivet-guard-core", + "rivet-metrics", + "rivet-pools", + "rivet-runtime", + "rivet-tunnel-protocol", + "rivet-util", "serde", "serde_json", - "simdutf8", - "value-trait", + "tokio", + "tokio-tungstenite", + "tracing", + "universalpubsub", + "url", + "uuid", + "versioned-data-util", ] [[package]] -name = "simdutf8" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" - -[[package]] -name = "simple_asn1" -version = "0.6.2" +name = "pem-rfc7468" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" dependencies = [ - "num-bigint", - "num-traits", - "thiserror 1.0.69", - "time 0.3.37", + "base64ct", ] [[package]] -name = "siphasher" -version = "0.3.11" +name = "percent-encoding" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] -name = "slab" -version = "0.4.9" +name = "pest" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323" dependencies = [ - "autocfg", + "memchr", + "thiserror 2.0.12", + "ucd-trie", ] [[package]] -name = "slotmap" -version = "1.0.7" +name = "pest_derive" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +checksum = "bb056d9e8ea77922845ec74a1c4e8fb17e7c218cc4fc11a15c5d25e189aa40bc" dependencies = [ - "version_check", + "pest", + "pest_generator", ] [[package]] -name = "sm3" -version = "0.4.2" +name = "pest_generator" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebb9a3b702d0a7e33bc4d85a14456633d2b165c2ad839c5fd9a8417c1ab15860" +checksum = "87e404e638f781eb3202dc82db6760c8ae8a1eeef7fb3fa8264b2ef280504966" dependencies = [ - "digest 0.10.7", + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "smallvec" -version = "1.13.2" +name = "pest_meta" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "edd1101f170f5903fde0914f899bb503d9ff5271d7ba76bbb70bea63690cc0d5" dependencies = [ - "serde", + "pest", + "sha2", ] [[package]] -name = "smartstring" -version = "1.0.1" +name = "phf" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ - "autocfg", - "static_assertions", - "version_check", + "phf_shared", ] [[package]] -name = "socket2" -version = "0.4.10" +name = "phf_shared" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ - "libc", - "winapi", + "siphasher", ] [[package]] -name = "socket2" -version = "0.5.8" +name = "pin-project" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" dependencies = [ - "libc", - "windows-sys 0.52.0", + "pin-project-internal", ] [[package]] -name = "sourcemap" -version = "8.0.1" +name = "pin-project-internal" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "208d40b9e8cad9f93613778ea295ed8f3c2b1824217c6cfc7219d3f6f45b96d4" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ - "base64-simd 0.7.0", - "bitvec", - "data-encoding", - "debugid", - "if_chain", - "rustc-hash 1.1.0", - "rustc_version 0.2.3", - "serde", - "serde_json", - "unicode-id-start", - "url", + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "sourcemap" -version = "9.1.2" +name = "pin-project-lite" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27c4ea7042fd1a155ad95335b5d505ab00d5124ea0332a06c8390d200bb1a76a" -dependencies = [ - "base64-simd 0.7.0", - "bitvec", - "data-encoding", - "debugid", - "if_chain", - "rustc-hash 1.1.0", - "rustc_version 0.2.3", - "serde", - "serde_json", - "unicode-id-start", - "url", -] +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] -name = "spin" -version = "0.5.2" +name = "pin-utils" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] -name = "spin" -version = "0.9.8" +name = "pkcs8" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "lock_api", + "der", + "spki", ] [[package]] -name = "spinning_top" -version = "0.3.0" +name = "pkg-config" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" -dependencies = [ - "lock_api", -] +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] -name = "spirv" -version = "0.3.0+sdk-1.3.268.0" +name = "portpicker" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +checksum = "be97d76faf1bfab666e1375477b23fde79eccf0276e9b63b92a39d676a889ba9" dependencies = [ - "bitflags 2.6.0", + "rand 0.8.5", ] [[package]] -name = "spki" -version = "0.6.0" +name = "postgres-protocol" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +checksum = "76ff0abab4a9b844b93ef7b81f1efc0a366062aaef2cd702c76256b5dc075c54" dependencies = [ - "base64ct", - "der 0.6.1", + "base64 0.22.1", + "byteorder", + "bytes", + "fallible-iterator", + "hmac", + "md-5", + "memchr", + "rand 0.9.2", + "sha2", + "stringprep", ] [[package]] -name = "spki" -version = "0.7.3" +name = "postgres-types" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +checksum = "613283563cd90e1dfc3518d548caee47e0e725455ed619881f5cf21f36de4b48" dependencies = [ - "base64ct", - "der 0.7.9", + "bytes", + "chrono", + "fallible-iterator", + "postgres-protocol", ] [[package]] -name = "sqlx" -version = "0.8.2" -source = "git+https://github.com/rivet-gg/sqlx?rev=aeeae14fe7a05aa05e72a4dad59998b8bd72ad3a#aeeae14fe7a05aa05e72a4dad59998b8bd72ad3a" +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" dependencies = [ - "sqlx-core", - "sqlx-macros", - "sqlx-mysql", - "sqlx-postgres", - "sqlx-sqlite", + "zerovec", ] [[package]] -name = "sqlx-core" -version = "0.8.2" -source = "git+https://github.com/rivet-gg/sqlx?rev=aeeae14fe7a05aa05e72a4dad59998b8bd72ad3a#aeeae14fe7a05aa05e72a4dad59998b8bd72ad3a" +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "bit-vec", - "bytes", - "crc", - "crossbeam-queue", - "either", - "event-listener", - "futures-core", - "futures-intrusive", - "futures-io", - "futures-util", - "hashbrown 0.14.5", - "hashlink 0.9.1", - "indexmap 2.7.0", - "ipnetwork", - "log", - "memchr", - "native-tls", - "once_cell", - "percent-encoding", - "rand 0.8.5", - "serde", - "serde_json", - "sha2 0.10.8", - "smallvec", - "thiserror 1.0.69", - "tokio", - "tokio-stream", - "tracing", - "url", - "uuid", + "zerocopy", ] [[package]] -name = "sqlx-macros" -version = "0.8.2" -source = "git+https://github.com/rivet-gg/sqlx?rev=aeeae14fe7a05aa05e72a4dad59998b8bd72ad3a#aeeae14fe7a05aa05e72a4dad59998b8bd72ad3a" +name = "pretty_assertions" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" dependencies = [ - "proc-macro2", - "quote", - "sqlx-core", - "sqlx-macros-core", - "syn 2.0.90", + "diff", + "yansi", ] [[package]] -name = "sqlx-macros-core" -version = "0.8.2" -source = "git+https://github.com/rivet-gg/sqlx?rev=aeeae14fe7a05aa05e72a4dad59998b8bd72ad3a#aeeae14fe7a05aa05e72a4dad59998b8bd72ad3a" +name = "prettyplease" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" dependencies = [ - "dotenvy", - "either", - "heck 0.5.0", - "hex", - "once_cell", "proc-macro2", - "quote", - "serde", - "serde_json", - "sha2 0.10.8", - "sqlx-core", - "sqlx-mysql", - "sqlx-postgres", - "sqlx-sqlite", - "syn 2.0.90", - "tempfile", - "tokio", - "url", + "syn 2.0.104", ] [[package]] -name = "sqlx-mysql" -version = "0.8.2" -source = "git+https://github.com/rivet-gg/sqlx?rev=aeeae14fe7a05aa05e72a4dad59998b8bd72ad3a#aeeae14fe7a05aa05e72a4dad59998b8bd72ad3a" +name = "proc-macro-crate" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" dependencies = [ - "atoi", - "base64 0.22.1", - "bitflags 2.6.0", - "byteorder", - "bytes", - "crc", - "digest 0.10.7", - "dotenvy", - "either", - "futures-channel", - "futures-core", - "futures-io", - "futures-util", - "generic-array", - "hex", - "hkdf", - "hmac 0.12.1", - "itoa 1.0.14", - "log", - "md-5", - "memchr", - "once_cell", - "percent-encoding", - "rand 0.8.5", - "rsa", - "serde", - "sha1", - "sha2 0.10.8", - "smallvec", - "sqlx-core", - "stringprep", - "thiserror 1.0.69", - "tracing", - "uuid", - "whoami", + "toml_edit", ] [[package]] -name = "sqlx-postgres" -version = "0.8.2" -source = "git+https://github.com/rivet-gg/sqlx?rev=aeeae14fe7a05aa05e72a4dad59998b8bd72ad3a#aeeae14fe7a05aa05e72a4dad59998b8bd72ad3a" -dependencies = [ - "atoi", - "base64 0.22.1", - "bit-vec", - "bitflags 2.6.0", - "byteorder", - "crc", - "dotenvy", - "etcetera 0.8.0", - "futures-channel", - "futures-core", - "futures-util", - "hex", - "hkdf", - "hmac 0.12.1", - "home", - "ipnetwork", - "itoa 1.0.14", - "log", - "md-5", - "memchr", - "once_cell", - "rand 0.8.5", - "serde", - "serde_json", - "sha2 0.10.8", - "smallvec", - "sqlx-core", - "stringprep", - "thiserror 1.0.69", - "tracing", - "uuid", - "whoami", +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", ] [[package]] -name = "sqlx-sqlite" -version = "0.8.2" -source = "git+https://github.com/rivet-gg/sqlx?rev=aeeae14fe7a05aa05e72a4dad59998b8bd72ad3a#aeeae14fe7a05aa05e72a4dad59998b8bd72ad3a" +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" dependencies = [ - "atoi", - "flume", - "futures-channel", - "futures-core", - "futures-executor", - "futures-intrusive", - "futures-util", - "libsqlite3-sys", - "log", - "percent-encoding", - "serde", - "serde_urlencoded", - "sqlx-core", - "tracing", - "url", - "uuid", + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "ssh-cipher" -version = "0.2.0" +name = "proc-macro2" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caac132742f0d33c3af65bfcde7f6aa8f62f0e991d80db99149eb9d44708784f" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ - "cipher", - "ssh-encoding", + "unicode-ident", ] [[package]] -name = "ssh-encoding" -version = "0.2.0" +name = "prost" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9242b9ef4108a78e8cd1a2c98e193ef372437f8c22be363075233321dd4a15" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" dependencies = [ - "base64ct", - "pem-rfc7468", - "sha2 0.10.8", + "bytes", + "prost-derive", ] [[package]] -name = "ssh-key" -version = "0.6.7" +name = "prost-derive" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b86f5297f0f04d08cabaa0f6bff7cb6aec4d9c3b49d87990d63da9d9156a8c3" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ - "p256 0.13.2", - "p384", - "p521", - "rand_core 0.6.4", - "rsa", - "sec1 0.7.3", - "sha2 0.10.8", - "signature 2.2.0", - "ssh-cipher", - "ssh-encoding", - "subtle", - "zeroize", + "anyhow", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "ssh2" -version = "0.9.4" +name = "prost-types" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7fe461910559f6d5604c3731d00d2aafc4a83d1665922e280f42f9a168d5455" +checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" dependencies = [ - "bitflags 1.3.2", - "libc", - "libssh2-sys", - "parking_lot 0.11.2", + "prost", ] [[package]] -name = "stable_deref_trait" -version = "1.2.0" +name = "protobuf" +version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" [[package]] -name = "stacker" -version = "0.1.17" +name = "quanta" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799c883d55abdb5e98af1a7b3f23b9b6de8ecada0ecac058672d7635eb48ca7b" +checksum = "f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7" dependencies = [ - "cc", - "cfg-if", + "crossbeam-utils", "libc", - "psm", - "windows-sys 0.59.0", + "once_cell", + "raw-cpuid", + "wasi 0.11.1+wasi-snapshot-preview1", + "web-sys", + "winapi", ] [[package]] -name = "static_assertions" -version = "1.1.0" +name = "quote" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] [[package]] -name = "statrs" -version = "0.18.0" +name = "r-efi" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a3fe7c28c6512e766b0874335db33c94ad7b8f9054228ae1c2abd47ce7d335e" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "radix_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" dependencies = [ - "approx", - "nalgebra", - "num-traits", - "rand 0.8.5", + "endian-type", + "nibble_vec", ] [[package]] -name = "string_enum" -version = "0.4.4" +name = "rand" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e383308aebc257e7d7920224fa055c632478d92744eca77f99be8fa1545b90" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "proc-macro2", - "quote", - "swc_macros_common", - "syn 2.0.90", + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", ] [[package]] -name = "stringcase" -version = "0.3.0" +name = "rand" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04028eeb851ed08af6aba5caa29f2d59a13ed168cee4d6bd753aeefcf1d636b0" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", +] [[package]] -name = "stringprep" -version = "0.1.5" +name = "rand_chacha" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ - "unicode-bidi", - "unicode-normalization", - "unicode-properties", + "ppv-lite86", + "rand_core 0.6.4", ] [[package]] -name = "strip-ansi-escapes" -version = "0.2.1" +name = "rand_chacha" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a8f8038e7e7969abb3f1b7c2a811225e9296da208539e0f79c5251d6cac0025" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ - "vte 0.14.1", + "ppv-lite86", + "rand_core 0.9.3", ] [[package]] -name = "strsim" -version = "0.10.0" +name = "rand_core" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] [[package]] -name = "strsim" -version = "0.11.1" +name = "rand_core" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", +] [[package]] -name = "structmeta" -version = "0.3.0" +name = "rand_distr" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e1575d8d40908d70f6fd05537266b90ae71b15dbbe7a8b7dffa2b759306d329" +checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ - "proc-macro2", - "quote", - "structmeta-derive", - "syn 2.0.90", + "num-traits", + "rand 0.8.5", ] [[package]] -name = "structmeta-derive" -version = "0.3.0" +name = "raw-cpuid" +version = "11.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc" +checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", + "bitflags", ] [[package]] -name = "strum" -version = "0.24.1" +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + +[[package]] +name = "redox_syscall" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +checksum = "7e8af0dde094006011e6a740d4879319439489813bd0bcdc7d821beaeeff48ec" dependencies = [ - "strum_macros 0.24.3", + "bitflags", ] [[package]] -name = "strum" -version = "0.25.0" +name = "redox_users" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "strum_macros 0.25.3", + "getrandom 0.2.16", + "libredox", + "thiserror 1.0.69", ] [[package]] -name = "strum" -version = "0.26.3" +name = "ref-cast" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" dependencies = [ - "strum_macros 0.26.4", + "ref-cast-impl", ] [[package]] -name = "strum_macros" -version = "0.24.3" +name = "ref-cast-impl" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" dependencies = [ - "heck 0.4.1", "proc-macro2", "quote", - "rustversion", - "syn 1.0.109", + "syn 2.0.104", ] [[package]] -name = "strum_macros" -version = "0.25.3" +name = "regex" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.90", + "aho-corasick", + "memchr", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", ] [[package]] -name = "strum_macros" -version = "0.26.4" +name = "regex-automata" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.90", + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-lite" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + +[[package]] +name = "reqwest" +version = "0.12.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.4.11", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "hyper 1.6.0", + "hyper-rustls", + "hyper-tls 0.6.0", + "hyper-util", + "js-sys", + "log", + "mime", + "mime_guess", + "native-tls", + "percent-encoding", + "pin-project-lite", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-native-tls", + "tower 0.5.2", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", ] [[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "swc_allocator" -version = "0.1.10" +name = "reserve-port" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76aa0eb65c0f39f9b6d82a7e5192c30f7ac9a78f084a21f270de1d8c600ca388" +checksum = "21918d6644020c6f6ef1993242989bf6d4952d2e025617744f184c02df51c356" dependencies = [ - "bumpalo", - "hashbrown 0.14.5", - "ptr_meta", - "rustc-hash 1.1.0", - "triomphe", + "thiserror 2.0.12", ] [[package]] -name = "swc_atoms" -version = "0.6.7" +name = "ring" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb6567e4e67485b3e7662b486f1565bdae54bd5b9d6b16b2ba1a9babb1e42125" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ - "hstr", - "once_cell", - "rustc-hash 1.1.0", - "serde", + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", ] [[package]] -name = "swc_cached" -version = "0.3.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83406221c501860fce9c27444f44125eafe9e598b8b81be7563d7036784cd05c" +name = "rivet-api-builder" +version = "0.0.1" dependencies = [ - "ahash 0.8.11", "anyhow", - "dashmap", - "once_cell", - "regex", + "axum 0.8.4", + "axum-test", + "chrono", + "gasoline", + "hyper 0.14.32", + "lazy_static", + "opentelemetry", + "rivet-cache", + "rivet-config", + "rivet-error", + "rivet-metrics", + "rivet-pools", "serde", + "serde_json", + "thiserror 1.0.69", + "tokio", + "tower 0.5.2", + "tower-http", + "tracing", + "tracing-opentelemetry", + "tracing-subscriber", + "uuid", ] [[package]] -name = "swc_common" -version = "0.37.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12d0a8eaaf1606c9207077d75828008cb2dfb51b095a766bd2b72ef893576e31" +name = "rivet-api-client" +version = "0.0.1" dependencies = [ - "ast_node", - "better_scoped_tls", - "cfg-if", - "either", - "from_variant", - "new_debug_unreachable", - "num-bigint", - "once_cell", - "rustc-hash 1.1.0", + "anyhow", + "axum 0.8.4", + "futures-util", + "reqwest", + "rivet-api-builder", + "rivet-api-util", + "rivet-config", + "rivet-error", + "rivet-pools", + "rivet-util", "serde", - "siphasher", - "sourcemap 9.1.2", - "swc_allocator", - "swc_atoms", - "swc_eq_ignore_macros", - "swc_visit", + "tokio", "tracing", - "unicode-width 0.1.14", - "url", ] [[package]] -name = "swc_config" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4740e53eaf68b101203c1df0937d5161a29f3c13bceed0836ddfe245b72dd000" +name = "rivet-api-full" +version = "0.0.1" dependencies = [ - "anyhow", - "indexmap 2.7.0", + "reqwest", "serde", "serde_json", - "swc_cached", - "swc_config_macro", -] - -[[package]] -name = "swc_config_macro" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c5f56139042c1a95b54f5ca48baa0e0172d369bcc9d3d473dad1de36bae8399" -dependencies = [ - "proc-macro2", - "quote", - "swc_macros_common", - "syn 2.0.90", + "serde_repr", + "serde_with", + "url", ] [[package]] -name = "swc_ecma_ast" -version = "0.118.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6f866d12e4d519052b92a0a86d1ac7ff17570da1272ca0c89b3d6f802cd79df" +name = "rivet-api-peer" +version = "0.0.1" dependencies = [ - "bitflags 2.6.0", - "is-macro", - "num-bigint", - "phf", - "scoped-tls", + "anyhow", + "axum 0.8.4", + "epoxy", + "futures-util", + "gasoline", + "indexmap 2.10.0", + "namespace", + "pegboard", + "rivet-api-builder", + "rivet-api-types", + "rivet-api-util", + "rivet-config", + "rivet-error", + "rivet-pools", + "rivet-types", + "rivet-util", "serde", - "string_enum", - "swc_atoms", - "swc_common", - "unicode-id-start", + "serde_json", + "tokio", + "tracing", + "utoipa", + "uuid", ] [[package]] -name = "swc_ecma_codegen" -version = "0.155.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7641608ef117cfbef9581a99d02059b522fcca75e5244fa0cbbd8606689c6f" +name = "rivet-api-public" +version = "0.0.1" dependencies = [ - "memchr", - "num-bigint", - "once_cell", + "anyhow", + "axum 0.8.4", + "epoxy", + "fs_extra", + "futures-util", + "gasoline", + "include_dir", + "namespace", + "pegboard", + "reqwest", + "rivet-api-builder", + "rivet-api-client", + "rivet-api-peer", + "rivet-api-types", + "rivet-api-util", + "rivet-config", + "rivet-error", + "rivet-pools", + "rivet-types", + "rivet-util", "serde", - "sourcemap 9.1.2", - "swc_allocator", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_codegen_macros", + "serde_json", + "tokio", "tracing", + "utoipa", ] [[package]] -name = "swc_ecma_codegen_macros" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859fabde36db38634f3fad548dd5e3410c1aebba1b67a3c63e67018fa57a0bca" +name = "rivet-api-runtime" +version = "0.0.1" dependencies = [ - "proc-macro2", - "quote", - "swc_macros_common", - "syn 2.0.90", + "reqwest", + "serde", + "serde_json", + "serde_repr", + "serde_with", + "url", ] [[package]] -name = "swc_ecma_loader" -version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55fa3d55045b97894bfb04d38aff6d6302ac8a6a38e3bb3dfb0d20475c4974a9" +name = "rivet-api-types" +version = "0.0.1" dependencies = [ "anyhow", - "pathdiff", + "gasoline", + "rivet-api-builder", + "rivet-runner-protocol", + "rivet-types", + "rivet-util", "serde", - "swc_atoms", - "swc_common", - "tracing", + "serde_json", + "utoipa", ] [[package]] -name = "swc_ecma_parser" -version = "0.149.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683dada14722714588b56481399c699378b35b2ba4deb5c4db2fb627a97fb54b" +name = "rivet-api-util" +version = "0.0.1" dependencies = [ - "either", - "new_debug_unreachable", - "num-bigint", - "num-traits", - "phf", + "anyhow", + "axum 0.8.4", + "reqwest", + "rivet-api-builder", "serde", - "smallvec", - "smartstring", - "stacker", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "tracing", - "typed-arena", + "serde_json", ] [[package]] -name = "swc_ecma_transforms_base" -version = "0.145.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65f21494e75d0bd8ef42010b47cabab9caaed8f2207570e809f6f4eb51a710d1" +name = "rivet-bootstrap" +version = "0.0.1" dependencies = [ - "better_scoped_tls", - "bitflags 2.6.0", - "indexmap 2.7.0", - "once_cell", - "phf", - "rustc-hash 1.1.0", + "epoxy", + "gasoline", + "namespace", + "rivet-config", + "rivet-metrics", + "rivet-runtime", "serde", - "smallvec", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_parser", - "swc_ecma_utils", - "swc_ecma_visit", + "tokio-tungstenite", "tracing", + "url", ] [[package]] -name = "swc_ecma_transforms_classes" -version = "0.134.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3d884594385bea9405a2e1721151470d9a14d3ceec5dd773c0ca6894791601" +name = "rivet-cache" +version = "0.0.1" dependencies = [ - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base", - "swc_ecma_utils", - "swc_ecma_visit", + "anyhow", + "futures-util", + "lazy_static", + "moka", + "rand 0.8.5", + "rivet-cache-result", + "rivet-config", + "rivet-env", + "rivet-metrics", + "rivet-pools", + "rivet-util", + "serde", + "serde_json", + "thiserror 1.0.69", + "tokio", + "tracing", + "uuid", ] [[package]] -name = "swc_ecma_transforms_macros" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500a1dadad1e0e41e417d633b3d6d5de677c9e0d3159b94ba3348436cdb15aab" +name = "rivet-cache-result" +version = "0.0.1" dependencies = [ - "proc-macro2", - "quote", - "swc_macros_common", - "syn 2.0.90", + "rivet-util", ] [[package]] -name = "swc_ecma_transforms_proposal" -version = "0.179.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79938ff510fc647febd8c6c3ef4143d099fdad87a223680e632623d056dae2dd" +name = "rivet-config" +version = "0.0.1" dependencies = [ - "either", - "rustc-hash 1.1.0", + "anyhow", + "config", + "dirs", + "glob", + "ipnet", + "json5", + "maplit", + "schemars 0.8.22", "serde", - "smallvec", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base", - "swc_ecma_transforms_classes", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", + "serde_json", + "url", + "uuid", ] [[package]] -name = "swc_ecma_transforms_react" -version = "0.191.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76c76d8b9792ce51401d38da0fa62158d61f6d80d16d68fe5b03ce4bf5fba383" +name = "rivet-dump-openapi" +version = "0.0.1" dependencies = [ - "base64 0.21.7", - "dashmap", - "indexmap 2.7.0", - "once_cell", - "serde", - "sha1", - "string_enum", - "swc_allocator", - "swc_atoms", - "swc_common", - "swc_config", - "swc_ecma_ast", - "swc_ecma_parser", - "swc_ecma_transforms_base", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", + "rivet-api-public", + "serde_json", + "utoipa", ] [[package]] -name = "swc_ecma_transforms_typescript" -version = "0.198.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15455da4768f97186c40523e83600495210c11825d3a44db43383fd81eace88d" +name = "rivet-engine" +version = "0.0.1" dependencies = [ - "ryu-js", + "anyhow", + "axum 0.8.4", + "base64 0.22.1", + "chrono", + "clap", + "colored_json", + "epoxy", + "futures-util", + "gasoline", + "hex", + "include_dir", + "lz4_flex", + "namespace", + "pegboard", + "pegboard-runner-ws", + "portpicker", + "rand 0.8.5", + "reqwest", + "rivet-api-peer", + "rivet-api-public", + "rivet-bootstrap", + "rivet-cache", + "rivet-config", + "rivet-guard", + "rivet-logs", + "rivet-pools", + "rivet-runner-protocol", + "rivet-runtime", + "rivet-service-manager", + "rivet-term", + "rivet-test-deps", + "rivet-util", + "rivet-workflow-worker", + "rstest", + "rustyline", "serde", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base", - "swc_ecma_transforms_react", - "swc_ecma_utils", - "swc_ecma_visit", + "serde_json", + "serde_yaml", + "strum", + "tabled", + "tempfile", + "thiserror 1.0.69", + "tokio", + "tokio-tungstenite", + "tracing", + "tracing-subscriber", + "udb-util", + "universaldb", + "url", + "uuid", + "versioned-data-util", ] [[package]] -name = "swc_ecma_utils" -version = "0.134.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029eec7dd485923a75b5a45befd04510288870250270292fc2c1b3a9e7547408" +name = "rivet-env" +version = "0.0.1" dependencies = [ - "indexmap 2.7.0", - "num_cpus", - "once_cell", - "rustc-hash 1.1.0", - "ryu-js", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_visit", - "tracing", - "unicode-id", + "anyhow", + "lazy_static", + "uuid", + "vergen", ] [[package]] -name = "swc_ecma_visit" -version = "0.104.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b1c6802e68e51f336e8bc9644e9ff9da75d7da9c1a6247d532f2e908aa33e81" +name = "rivet-error" +version = "0.0.1" dependencies = [ - "new_debug_unreachable", - "num-bigint", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_visit", - "tracing", + "anyhow", + "indoc", + "rivet-error-macros", + "serde", + "serde_json", + "uuid", ] [[package]] -name = "swc_eq_ignore_macros" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63db0adcff29d220c3d151c5b25c0eabe7e32dd936212b84cdaa1392e3130497" +name = "rivet-error-macros" +version = "0.0.1" dependencies = [ + "indoc", "proc-macro2", "quote", - "syn 2.0.90", + "serde_json", + "syn 2.0.104", ] [[package]] -name = "swc_macros_common" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f486687bfb7b5c560868f69ed2d458b880cebc9babebcb67e49f31b55c5bf847" +name = "rivet-guard" +version = "0.0.1" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", + "anyhow", + "axum 0.8.4", + "bytes", + "futures", + "gasoline", + "http-body 1.0.1", + "http-body-util", + "hyper 1.6.0", + "hyper-tungstenite", + "indoc", + "once_cell", + "pegboard", + "pegboard-gateway", + "pegboard-tunnel", + "regex", + "rivet-api-peer", + "rivet-api-public", + "rivet-cache", + "rivet-config", + "rivet-error", + "rivet-guard-core", + "rivet-key-data", + "rivet-logs", + "rivet-metrics", + "rivet-pools", + "rivet-runtime", + "rustls 0.23.29", + "rustls-pemfile 2.2.0", + "serde", + "serde_json", + "tokio", + "tower 0.5.2", + "tracing", + "udb-util", + "universaldb", + "url", + "uuid", ] [[package]] -name = "swc_visit" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ceb044142ba2719ef9eb3b6b454fce61ab849eb696c34d190f04651955c613d" +name = "rivet-guard-core" +version = "0.0.1" dependencies = [ - "either", - "new_debug_unreachable", + "anyhow", + "async-trait", + "bytes", + "clickhouse-inserter", + "clickhouse-user-query", + "futures", + "futures-util", + "gasoline", + "http-body 1.0.1", + "http-body-util", + "hyper 1.6.0", + "hyper-tungstenite", + "hyper-util", + "indoc", + "lazy_static", + "moka", + "once_cell", + "pegboard", + "rand 0.8.5", + "regex", + "reqwest", + "rivet-api-builder", + "rivet-config", + "rivet-error", + "rivet-metrics", + "rivet-util", + "rustls 0.23.29", + "rustls-pemfile 2.2.0", + "serde", + "serde_json", + "tokio", + "tokio-rustls 0.26.2", + "tokio-stream", + "tokio-tungstenite", + "tracing", + "tracing-subscriber", + "url", + "uuid", ] [[package]] -name = "swc_visit_macros" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92807d840959f39c60ce8a774a3f83e8193c658068e6d270dbe0a05e40e90b41" +name = "rivet-key-data" +version = "0.0.1" dependencies = [ - "Inflector", - "proc-macro2", - "quote", - "swc_macros_common", - "syn 2.0.90", + "anyhow", + "bare_gen", + "gasoline", + "indoc", + "prettyplease", + "rivet-runner-protocol", + "rivet-util", + "serde", + "serde_bare", + "serde_json", + "syn 2.0.104", + "versioned-data-util", ] [[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +name = "rivet-logs" +version = "0.0.1" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "anyhow", + "chrono", + "nix 0.30.1", + "tokio", + "tracing", + "tracing-logfmt", + "tracing-subscriber", + "windows 0.58.0", ] [[package]] -name = "syn" -version = "2.0.90" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +name = "rivet-metrics" +version = "0.0.1" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "anyhow", + "console-subscriber", + "hyper 0.14.32", + "lazy_static", + "opentelemetry", + "opentelemetry-otlp", + "opentelemetry-semantic-conventions", + "opentelemetry_sdk", + "rivet-config", + "rivet-env", + "tokio", + "tracing", ] [[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - -[[package]] -name = "sync_wrapper" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +name = "rivet-pools" +version = "0.0.1" dependencies = [ - "futures-core", + "anyhow", + "async-nats", + "clickhouse", + "clickhouse-inserter", + "divan", + "futures-util", + "governor", + "hyper 0.14.32", + "hyper-tls 0.5.0", + "lazy_static", + "reqwest", + "rivet-config", + "rivet-metrics", + "rivet-util", + "serde", + "tempfile", + "thiserror 1.0.69", + "tokio", + "tokio-native-tls", + "tokio-util", + "tracing", + "tracing-logfmt", + "tracing-subscriber", + "udb-util", + "universaldb", + "universalpubsub", + "url", + "uuid", ] [[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +name = "rivet-runner-protocol" +version = "0.0.1" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "unicode-xid", + "anyhow", + "bare_gen", + "base64 0.22.1", + "gasoline", + "indoc", + "prettyplease", + "rivet-util", + "serde", + "serde_bare", + "serde_json", + "syn 2.0.104", + "utoipa", + "versioned-data-util", ] [[package]] -name = "synstructure" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +name = "rivet-runtime" +version = "0.0.1" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", + "console-subscriber", + "lazy_static", + "opentelemetry", + "opentelemetry-appender-tracing", + "opentelemetry-otlp", + "opentelemetry-semantic-conventions", + "opentelemetry-stdout", + "opentelemetry_sdk", + "reqwest", + "rivet-env", + "rivet-metrics", + "serde", + "serde_json", + "thiserror 1.0.69", + "tokio", + "tracing", + "tracing-core", + "tracing-logfmt", + "tracing-opentelemetry", + "tracing-subscriber", ] [[package]] -name = "sysinfo" -version = "0.31.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be" +name = "rivet-service-manager" +version = "0.0.1" dependencies = [ - "core-foundation-sys", - "libc", - "memchr", - "ntapi", - "rayon", - "windows 0.57.0", + "anyhow", + "chrono", + "include_dir", + "rivet-config", + "rivet-metrics", + "rivet-pools", + "tokio", + "tokio-cron-scheduler", + "tracing", ] [[package]] -name = "sysinfo" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c33cd241af0f2e9e3b5c32163b873b29956890b5342e6745b917ce9d490f4af" +name = "rivet-term" +version = "0.1.0" +source = "git+https://github.com/rivet-gg/rivet-term?rev=55e328470b68c557fb9bc8298369f90182d35b6d#55e328470b68c557fb9bc8298369f90182d35b6d" dependencies = [ - "core-foundation-sys", - "libc", - "memchr", - "ntapi", - "rayon", - "windows 0.57.0", + "console", + "derive_builder 0.12.0", + "tabled", + "term_size", + "thiserror 1.0.69", + "tokio", ] [[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +name = "rivet-test-deps" +version = "0.0.1" dependencies = [ - "bitflags 1.3.2", - "core-foundation 0.9.4", - "system-configuration-sys 0.5.0", + "anyhow", + "futures-util", + "portpicker", + "rivet-cache", + "rivet-config", + "rivet-pools", + "rivet-test-deps-docker", + "tokio", + "tracing", + "tracing-subscriber", + "url", + "uuid", ] [[package]] -name = "system-configuration" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +name = "rivet-test-deps-docker" +version = "0.0.1" dependencies = [ - "bitflags 2.6.0", - "core-foundation 0.9.4", - "system-configuration-sys 0.6.0", + "anyhow", + "portpicker", + "rivet-config", + "tokio", + "tokio-postgres", + "tracing", + "uuid", ] [[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +name = "rivet-tunnel-protocol" +version = "0.0.1" dependencies = [ - "core-foundation-sys", - "libc", + "anyhow", + "bare_gen", + "base64 0.22.1", + "gasoline", + "indoc", + "prettyplease", + "rivet-util", + "serde", + "serde_bare", + "serde_json", + "syn 2.0.104", + "versioned-data-util", ] [[package]] -name = "system-configuration-sys" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +name = "rivet-types" +version = "0.0.1" dependencies = [ - "core-foundation-sys", - "libc", + "anyhow", + "gasoline", + "rivet-api-builder", + "rivet-key-data", + "rivet-runner-protocol", + "rivet-util", + "serde", + "utoipa", ] [[package]] -name = "tabled" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6709222f3973137427ce50559cd564dc187a95b9cfe01613d2f4e93610e510a" +name = "rivet-util" +version = "0.0.1" dependencies = [ - "ansi-str", - "ansitok", - "papergrid", - "tabled_derive", + "anyhow", + "async-trait", + "axum 0.8.4", + "bcrypt", + "chrono", + "futures-util", + "indexmap 2.10.0", + "ipnet", + "lazy_static", + "rand 0.8.5", + "regex", + "reqwest", + "rivet-config", + "rivet-metrics", + "rivet-util-id", + "serde", + "serde_json", + "thiserror 1.0.69", + "tokio", + "tracing", + "url", + "utoipa", + "uuid", ] [[package]] -name = "tabled_derive" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "931be476627d4c54070a1f3a9739ccbfec9b36b39815106a20cce2243bbcefe1" +name = "rivet-util-id" +version = "0.0.1" dependencies = [ - "heck 0.4.1", - "proc-macro-error2", - "proc-macro2", - "quote", - "syn 1.0.109", + "serde", + "thiserror 1.0.69", + "udb-util", + "utoipa", + "uuid", ] [[package]] -name = "tagptr" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tar" -version = "0.4.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c65998313f8e17d0d553d28f91a0df93e4dbbbf770279c7bc21ca0f09ea1a1f6" +name = "rivet-workflow-worker" +version = "0.0.1" dependencies = [ - "filetime", - "libc", - "xattr", + "anyhow", + "epoxy", + "gasoline", + "namespace", + "pegboard", + "rivet-config", + "tracing", ] [[package]] -name = "team-avatar-upload-complete" -version = "25.5.2" +name = "rocksdb" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddb7af00d2b17dbd07d82c0063e25411959748ff03e8d4f96134c2ff41fce34f" dependencies = [ - "chirp-client", - "chirp-worker", - "faker-team", - "prost 0.10.4", - "reqwest 0.11.27", - "rivet-operation", - "sqlx", - "upload-complete", - "upload-get", - "upload-prepare", + "libc", + "librocksdb-sys", ] [[package]] -name = "team-get" -version = "25.5.2" +name = "rstest" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5a3193c063baaa2a95a33f03035c8a72b83d97a54916055ba22d35ed3839d49" dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", - "upload-file-list", - "upload-get", + "futures-timer", + "futures-util", + "rstest_macros", ] [[package]] -name = "team-invite-get" -version = "25.5.2" +name = "rstest_macros" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c845311f0ff7951c5506121a9ad75aec44d083c31583b2ea5a30bcb0b0abba0" dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "prost 0.10.4", - "rivet-operation", - "sqlx", + "cfg-if", + "glob", + "proc-macro-crate", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version", + "syn 2.0.104", + "unicode-ident", ] [[package]] -name = "team-invite-worker" -version = "25.5.2" +name = "rust-multipart-rfc7578_2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c839d037155ebc06a571e305af66ff9fd9063a6e662447051737e1ac75beea41" dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "rivet-config", - "rivet-health-checks", - "rivet-metrics", - "rivet-runtime", - "sqlx", - "team-member-list", - "team-user-ban-get", + "bytes", + "futures-core", + "futures-util", + "http 1.3.1", + "mime", + "rand 0.9.2", + "thiserror 2.0.12", ] [[package]] -name = "team-join-request-list" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] +name = "rustc-demangle" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" [[package]] -name = "team-member-count" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] -name = "team-member-get" -version = "25.5.2" +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", + "semver", ] [[package]] -name = "team-member-list" -version = "25.5.2" +name = "rustix" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.60.2", ] [[package]] -name = "team-member-relationship-get" -version = "25.5.2" +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ - "chirp-client", - "chirp-worker", - "faker-team", - "prost 0.10.4", - "rivet-operation", - "sqlx", + "log", + "ring", + "rustls-webpki 0.101.7", + "sct", ] [[package]] -name = "team-profile-validate" -version = "25.5.2" +name = "rustls" +version = "0.23.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2491382039b29b9b11ff08b76ff6c97cf287671dbb74f0be44bda389fffe9bd1" dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki 0.103.4", + "subtle", + "zeroize", ] [[package]] -name = "team-recommend" -version = "25.5.2" +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", + "openssl-probe", + "rustls-pemfile 1.0.4", + "schannel", + "security-framework", ] [[package]] -name = "team-resolve-display-name" -version = "25.5.2" +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "chirp-client", - "chirp-worker", - "faker-team", - "prost 0.10.4", - "rivet-operation", - "sqlx", - "team-get", + "base64 0.21.7", ] [[package]] -name = "team-user-ban-get" -version = "25.5.2" +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", + "rustls-pki-types", ] [[package]] -name = "team-user-ban-list" -version = "25.5.2" +name = "rustls-pki-types" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", + "zeroize", ] [[package]] -name = "team-validate" -version = "25.5.2" +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "team-resolve-display-name", + "ring", + "untrusted", ] [[package]] -name = "team-worker" -version = "25.5.2" +name = "rustls-webpki" +version = "0.103.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" dependencies = [ - "chirp-client", - "chirp-worker", - "faker-team", - "game-namespace-list", - "mm-lobby-list-for-namespace", - "reqwest 0.11.27", - "rivet-config", - "rivet-health-checks", - "rivet-metrics", - "rivet-runtime", - "serde", - "team-join-request-list", - "team-profile-validate", - "team-user-ban-get", - "team-validate", - "user-identity-get", + "ring", + "rustls-pki-types", + "untrusted", ] [[package]] -name = "telemetry-beacon" -version = "25.5.2" -dependencies = [ - "async-posthog", - "chirp-client", - "chirp-worker", - "chirp-workflow", - "chrono", - "cloud-version-get", - "dynamic-config", - "futures-util", - "game-get", - "game-namespace-get", - "game-version-get", - "indoc 1.0.9", - "lazy_static", - "mm-player-count-for-namespace", - "pegboard", - "prost 0.10.4", - "rivet-config", - "rivet-connection", - "rivet-env", - "rivet-operation", - "rivet-pools", - "rivet-runtime", - "serde", - "sqlx", - "sysinfo 0.32.1", - "team-get", - "team-member-count", - "tokio", - "tracing", - "tracing-logfmt", - "tracing-subscriber", -] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] -name = "tempfile" -version = "3.14.0" +name = "rustyline" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +checksum = "2ee1e066dc922e513bda599c6ccb5f3bb2b0ea5870a579448f2622993f0a9a2f" dependencies = [ + "bitflags", "cfg-if", - "fastrand 2.2.0", - "once_cell", - "rustix", + "clipboard-win", + "fd-lock", + "home", + "libc", + "log", + "memchr", + "nix 0.29.0", + "radix_trie", + "unicode-segmentation", + "unicode-width", + "utf8parse", "windows-sys 0.59.0", ] [[package]] -name = "term_size" -version = "0.3.2" +name = "ryu" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9" -dependencies = [ - "libc", - "winapi", -] +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] -name = "termcolor" -version = "1.4.1" +name = "safe_arch" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" dependencies = [ - "winapi-util", + "bytemuck", ] [[package]] -name = "terminal_size" -version = "0.4.1" +name = "schannel" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ - "rustix", "windows-sys 0.59.0", ] [[package]] -name = "termtree" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" - -[[package]] -name = "testcontainers" -version = "0.12.0" +name = "schemars" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5e3ed6e3598dbf32cba8cb356b881c085e0adea57597f387723430dd94b4084" +checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" dependencies = [ - "hex", - "hmac 0.10.1", - "log", - "rand 0.8.5", + "dyn-clone", + "schemars_derive", "serde", "serde_json", - "sha2 0.9.9", + "url", + "uuid", ] [[package]] -name = "testcontainers" -version = "0.24.0" +name = "schemars" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23bb7577dca13ad86a78e8271ef5d322f37229ec83b8d98da6d996c588a1ddb1" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" dependencies = [ - "async-trait", - "bollard", - "bollard-stubs", - "bytes", - "docker_credential", - "either", - "etcetera 0.10.0", - "futures", - "log", - "memchr", - "parse-display", - "pin-project-lite", + "dyn-clone", + "ref-cast", "serde", "serde_json", - "serde_with 3.12.0", - "thiserror 2.0.12", - "tokio", - "tokio-stream", - "tokio-tar", - "tokio-util 0.7.12", - "url", ] [[package]] -name = "text_lines" -version = "0.6.0" +name = "schemars" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fd5828de7deaa782e1dd713006ae96b3bee32d3279b79eb67ecf8072c059bcf" +checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" dependencies = [ + "dyn-clone", + "ref-cast", "serde", + "serde_json", ] [[package]] -name = "thiserror" -version = "1.0.69" +name = "schemars_derive" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" dependencies = [ - "thiserror-impl 1.0.69", + "proc-macro2", + "quote", + "serde_derive_internals 0.29.1", + "syn 2.0.104", ] [[package]] -name = "thiserror" -version = "2.0.12" +name = "scoped-tls" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" -dependencies = [ - "thiserror-impl 2.0.12", -] +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] -name = "thiserror-impl" -version = "1.0.69" +name = "scopeguard" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] -name = "thiserror-impl" -version = "2.0.12" +name = "sct" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", + "ring", + "untrusted", ] [[package]] -name = "thread_local" -version = "1.1.8" +name = "sealed" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +checksum = "6b5e421024b5e5edfbaa8e60ecf90bda9dbffc602dbb230e6028763f85f0c68c" dependencies = [ - "cfg-if", - "once_cell", + "heck 0.3.3", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] -name = "tier" -version = "25.5.2" +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "chirp-workflow", - "cluster", - "linode", - "rivet-config", - "server-spec", + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", ] [[package]] -name = "time" -version = "0.1.45" +name = "security-framework-sys" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ + "core-foundation-sys", "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", ] [[package]] -name = "time" -version = "0.3.37" +name = "seize" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +checksum = "e4b8d813387d566f627f3ea1b914c068aac94c40ae27ec43f5f33bde65abefe7" dependencies = [ - "deranged", - "itoa 1.0.14", "libc", - "num-conv", - "num_threads", - "powerfmt", - "serde", - "time-core", - "time-macros", + "windows-sys 0.52.0", ] [[package]] -name = "time-core" -version = "0.1.2" +name = "semver" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] -name = "time-macros" -version = "0.2.19" +name = "serde" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ - "num-conv", - "time-core", + "serde_derive", ] [[package]] -name = "tiny_http" -version = "0.12.0" +name = "serde_bare" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389915df6413a2e74fb181895f933386023c71110878cd0825588928e64cdc82" +checksum = "51c55386eed0f1ae957b091dc2ca8122f287b60c79c774cbe3d5f2b69fded660" dependencies = [ - "ascii", - "chunked_transfer", - "httpdate", - "log", + "serde", ] [[package]] -name = "tinystr" -version = "0.7.6" +name = "serde_derive" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ - "displaydoc", - "zerovec", + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "tinyvec" -version = "1.8.0" +name = "serde_derive_internals" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" dependencies = [ - "tinyvec_macros", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] -name = "tinyvec_macros" -version = "0.1.1" +name = "serde_derive_internals" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "token-create" -version = "25.5.2" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ - "base64 0.13.1", - "chirp-client", - "chirp-worker", - "chrono", - "jsonwebtoken", - "lazy_static", - "prost 0.10.4", - "rivet-claims", - "rivet-operation", - "sqlx", + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "token-exchange" -version = "25.5.2" +name = "serde_json" +version = "1.0.141" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3" dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "prost 0.10.4", - "rivet-operation", - "sqlx", - "token-create", + "itoa 1.0.15", + "memchr", + "ryu", + "serde", ] [[package]] -name = "token-get" -version = "25.5.2" +name = "serde_nanos" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a93142f0367a4cc53ae0fead1bcda39e85beccfad3dcd717656cacab94b12985" dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "prost 0.10.4", - "rivet-operation", - "sqlx", - "token-create", + "serde", ] [[package]] -name = "token-revoke" -version = "25.5.2" +name = "serde_path_to_error" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "prost 0.10.4", - "rivet-operation", - "sqlx", - "token-create", + "itoa 1.0.15", + "serde", ] [[package]] -name = "tokio" -version = "1.44.1" +name = "serde_repr" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ - "backtrace", - "bytes", - "libc", - "mio 1.0.3", - "parking_lot 0.12.3", - "pin-project-lite", - "signal-hook-registry", - "socket2 0.5.8", - "tokio-macros", - "tracing", - "windows-sys 0.52.0", + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "tokio-cron-scheduler" -version = "0.13.0" +name = "serde_urlencoded" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a5597b569b4712cf78aa0c9ae29742461b7bda1e49c2a5fdad1d79bf022f8f0" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ - "chrono", - "croner", - "num-derive", - "num-traits", - "tokio", - "tracing", - "uuid", + "form_urlencoded", + "itoa 1.0.15", + "ryu", + "serde", ] [[package]] -name = "tokio-eld" -version = "0.2.0" +name = "serde_with" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9166030f05d6bc5642bdb8f8c2be31eb3c02cd465d662bcdc2df82d4aa41a584" +checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5" dependencies = [ - "hdrhistogram", - "tokio", + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.10.0", + "schemars 0.9.0", + "schemars 1.0.4", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", ] [[package]] -name = "tokio-macros" -version = "2.5.0" +name = "serde_with_macros" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f" dependencies = [ + "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.90", -] - -[[package]] -name = "tokio-metrics" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eace09241d62c98b7eeb1107d4c5c64ca3bd7da92e8c218c153ab3a78f9be112" -dependencies = [ - "futures-util", - "pin-project-lite", - "tokio", - "tokio-stream", + "syn 2.0.104", ] [[package]] -name = "tokio-native-tls" -version = "0.3.1" +name = "serde_yaml" +version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "native-tls", - "tokio", + "indexmap 2.10.0", + "itoa 1.0.15", + "ryu", + "serde", + "unsafe-libyaml", ] [[package]] -name = "tokio-retry" -version = "0.3.0" +name = "sha1" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "pin-project", - "rand 0.8.5", - "tokio", + "cfg-if", + "cpufeatures", + "digest", ] [[package]] -name = "tokio-rustls" -version = "0.22.0" +name = "sha2" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ - "rustls 0.19.1", - "tokio", - "webpki 0.21.4", + "cfg-if", + "cpufeatures", + "digest", ] [[package]] -name = "tokio-rustls" -version = "0.24.1" +name = "sharded-slab" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ - "rustls 0.21.12", - "tokio", + "lazy_static", ] [[package]] -name = "tokio-rustls" -version = "0.26.2" +name = "shlex" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" -dependencies = [ - "rustls 0.23.25", - "tokio", -] +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] -name = "tokio-socks" -version = "0.5.2" +name = "signal-hook-registry" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" dependencies = [ - "either", - "futures-util", - "thiserror 1.0.69", - "tokio", + "libc", ] [[package]] -name = "tokio-stream" -version = "0.1.16" +name = "signatory" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +checksum = "c1e303f8205714074f6068773f0e29527e0453937fe837c9717d066635b65f31" dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", + "pkcs8", + "rand_core 0.6.4", + "signature", + "zeroize", ] [[package]] -name = "tokio-tar" -version = "0.3.1" +name = "signature" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5714c010ca3e5c27114c1cdeb9d14641ace49874aa5626d7149e47aedace75" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ - "filetime", - "futures-core", - "libc", - "redox_syscall 0.3.5", - "tokio", - "tokio-stream", - "xattr", + "digest", + "rand_core 0.6.4", ] [[package]] -name = "tokio-tungstenite" -version = "0.21.0" +name = "simba" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" +checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa" dependencies = [ - "futures-util", - "log", - "native-tls", - "tokio", - "tokio-native-tls", - "tungstenite 0.21.0", + "approx", + "num-complex", + "num-traits", + "paste", + "wide", ] [[package]] -name = "tokio-tungstenite" -version = "0.23.1" +name = "siphasher" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6989540ced10490aaf14e6bad2e3d33728a2813310a0c71d1574304c49631cd" -dependencies = [ - "futures-util", - "log", - "tokio", - "tungstenite 0.23.0", -] +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] -name = "tokio-tungstenite" -version = "0.26.2" +name = "slab" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" -dependencies = [ - "futures-util", - "log", - "tokio", - "tungstenite 0.26.2", -] +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" [[package]] -name = "tokio-util" -version = "0.6.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "log", - "pin-project-lite", - "tokio", -] +name = "slog" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8347046d4ebd943127157b94d63abb990fcf729dc4e9978927fdf4ac3c998d06" [[package]] -name = "tokio-util" -version = "0.7.12" +name = "slog-async" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "72c8038f898a2c79507940990f05386455b3a317d8f18d4caea7cbc3d5096b84" dependencies = [ - "bytes", - "futures-core", - "futures-io", - "futures-sink", - "futures-util", - "hashbrown 0.14.5", - "pin-project-lite", - "slab", - "tokio", + "crossbeam-channel", + "slog", + "take_mut", + "thread_local", ] [[package]] -name = "toml" -version = "0.5.11" +name = "slog-term" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +checksum = "b6e022d0b998abfe5c3782c1f03551a596269450ccd677ea51c56f8b214610e8" dependencies = [ - "serde", + "is-terminal", + "slog", + "term", + "thread_local", + "time", ] [[package]] -name = "toml" -version = "0.7.8" +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", + "libc", + "windows-sys 0.52.0", ] [[package]] -name = "toml_datetime" -version = "0.6.8" +name = "socket2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" dependencies = [ - "serde", + "libc", + "windows-sys 0.59.0", ] [[package]] -name = "toml_edit" -version = "0.19.15" +name = "spinning_top" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" dependencies = [ - "indexmap 2.7.0", - "serde", - "serde_spanned", - "toml_datetime", - "winnow", + "lock_api", ] [[package]] -name = "tonic" -version = "0.12.3" +name = "spki" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ - "async-stream", - "async-trait", - "axum", - "base64 0.22.1", - "bytes", - "h2 0.4.7", - "http 1.1.0", - "http-body 1.0.1", - "http-body-util", - "hyper 1.6.0", - "hyper-timeout", - "hyper-util", - "percent-encoding", - "pin-project", - "prost 0.13.4", - "socket2 0.5.8", - "tokio", - "tokio-stream", - "tower 0.4.13", - "tower-layer", - "tower-service", - "tracing", + "base64ct", + "der", ] [[package]] -name = "tower" -version = "0.4.13" +name = "stable_deref_trait" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "statrs" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a3fe7c28c6512e766b0874335db33c94ad7b8f9054228ae1c2abd47ce7d335e" dependencies = [ - "futures-core", - "futures-util", - "indexmap 1.9.3", - "pin-project", - "pin-project-lite", + "approx", + "nalgebra", + "num-traits", "rand 0.8.5", - "slab", - "tokio", - "tokio-util 0.7.12", - "tower-layer", - "tower-service", - "tracing", ] [[package]] -name = "tower" -version = "0.5.2" +name = "stringprep" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" dependencies = [ - "futures-core", - "futures-util", - "pin-project-lite", - "sync_wrapper 1.0.2", - "tokio", - "tower-layer", - "tower-service", + "unicode-bidi", + "unicode-normalization", + "unicode-properties", ] [[package]] -name = "tower-http" -version = "0.6.2" +name = "strsim" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403fa3b783d4b626a8ad51d766ab03cb6d2dbfc46b1c5d4448395e6628dc9697" -dependencies = [ - "async-compression", - "bitflags 2.6.0", - "bytes", - "futures-core", - "http 1.1.0", - "http-body 1.0.1", - "http-body-util", - "pin-project-lite", - "tokio", - "tokio-util 0.7.12", - "tower-layer", - "tower-service", -] +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] -name = "tower-layer" -version = "0.3.3" +name = "strsim" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] -name = "tower-service" -version = "0.3.3" +name = "strum" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] [[package]] -name = "tracing" -version = "0.1.41" +name = "strum_macros" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.104", ] [[package]] -name = "tracing-attributes" -version = "0.1.28" +name = "subtle" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "unicode-ident", ] [[package]] -name = "tracing-core" -version = "0.1.33" +name = "syn" +version = "2.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ - "once_cell", - "valuable", + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] -name = "tracing-futures" -version = "0.2.5" +name = "sync_wrapper" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ - "pin-project", - "tracing", + "futures-core", ] [[package]] -name = "tracing-log" -version = "0.2.0" +name = "synstructure" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ - "log", - "once_cell", - "tracing-core", + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "tracing-logfmt" -version = "0.3.5" +name = "system-configuration" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1f47d22deb79c3f59fcf2a1f00f60cbdc05462bf17d1cd356c1fefa3f444bd" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "nu-ansi-term 0.50.1", - "time 0.3.37", - "tracing", - "tracing-core", - "tracing-subscriber", + "bitflags", + "core-foundation", + "system-configuration-sys", ] [[package]] -name = "tracing-opentelemetry" -version = "0.29.0" +name = "system-configuration-sys" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721f2d2569dce9f3dfbbddee5906941e953bfcdf736a62da3377f5751650cc36" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" dependencies = [ - "js-sys", - "once_cell", - "opentelemetry 0.28.0", - "opentelemetry_sdk 0.28.0", - "smallvec", - "tracing", - "tracing-core", - "tracing-log", - "tracing-subscriber", - "web-time", + "core-foundation-sys", + "libc", ] [[package]] -name = "tracing-serde" -version = "0.2.0" +name = "tabled" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" +checksum = "c6709222f3973137427ce50559cd564dc187a95b9cfe01613d2f4e93610e510a" dependencies = [ - "serde", - "tracing-core", + "ansi-str", + "ansitok", + "papergrid", + "tabled_derive", ] [[package]] -name = "tracing-subscriber" -version = "0.3.19" +name = "tabled_derive" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +checksum = "931be476627d4c54070a1f3a9739ccbfec9b36b39815106a20cce2243bbcefe1" dependencies = [ - "matchers", - "nu-ansi-term 0.46.0", - "once_cell", - "regex", - "serde", - "serde_json", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", - "tracing-serde", + "heck 0.4.1", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] -name = "triomphe" -version = "0.1.14" +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + +[[package]] +name = "take_mut" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" + +[[package]] +name = "tempfile" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef8f7726da4807b58ea5c96fdc122f80702030edc33b35aff9190a51148ccc85" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ - "serde", - "stable_deref_trait", + "fastrand", + "getrandom 0.3.3", + "once_cell", + "rustix", + "windows-sys 0.59.0", ] [[package]] -name = "trust-dns-proto" -version = "0.23.2" +name = "term" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3119112651c157f4488931a01e586aa459736e9d6046d3bd9105ffb69352d374" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" dependencies = [ - "async-trait", - "cfg-if", - "data-encoding", - "enum-as-inner", - "futures-channel", - "futures-io", - "futures-util", - "idna 0.4.0", - "ipnet", - "native-tls", - "once_cell", - "rand 0.8.5", - "smallvec", - "thiserror 1.0.69", - "tinyvec", - "tokio", - "tokio-native-tls", - "tracing", - "url", + "dirs-next", + "rustversion", + "winapi", ] [[package]] -name = "trust-dns-resolver" -version = "0.23.2" +name = "term_size" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a3e6c3aff1718b3c73e395d1f35202ba2ffa847c6a62eea0db8fb4cfe30be6" +checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9" dependencies = [ - "cfg-if", - "futures-util", - "ipconfig", - "lru-cache", - "once_cell", - "parking_lot 0.12.3", - "rand 0.8.5", - "resolv-conf", - "smallvec", - "thiserror 1.0.69", - "tokio", - "tokio-native-tls", - "tracing", - "trust-dns-proto", + "libc", + "winapi", ] [[package]] -name = "try-lock" -version = "0.2.5" +name = "terminal_size" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed" +dependencies = [ + "rustix", + "windows-sys 0.59.0", +] [[package]] -name = "try_map" -version = "0.3.1" +name = "thiserror" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb1626d07cb5c1bb2cf17d94c0be4852e8a7c02b041acec9a8c5bdda99f9d580" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] [[package]] -name = "tungstenite" -version = "0.21.0" +name = "thiserror" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http 1.1.0", - "httparse", - "log", - "native-tls", - "rand 0.8.5", - "sha1", - "thiserror 1.0.69", - "url", - "utf-8", + "thiserror-impl 2.0.12", ] [[package]] -name = "tungstenite" -version = "0.23.0" +name = "thiserror-impl" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http 1.1.0", - "httparse", - "log", - "rand 0.8.5", - "sha1", - "thiserror 1.0.69", - "utf-8", + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "tungstenite" -version = "0.26.2" +name = "thiserror-impl" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ - "bytes", - "data-encoding", - "http 1.1.0", - "httparse", - "log", - "rand 0.9.0", - "sha1", - "thiserror 2.0.12", - "utf-8", + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "twox-hash" -version = "1.6.3" +name = "thread_local" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if", - "rand 0.8.5", - "static_assertions", ] [[package]] -name = "typed-arena" -version = "2.0.2" +name = "time" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +dependencies = [ + "deranged", + "itoa 1.0.15", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] [[package]] -name = "typed-path" -version = "0.7.1" +name = "time-core" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668404597c2c687647f6f8934f97c280fd500db28557f52b07c56b92d3dc500a" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] -name = "typenum" -version = "1.17.0" +name = "time-macros" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" +dependencies = [ + "num-conv", + "time-core", +] [[package]] -name = "types-proto" -version = "25.5.2" +name = "tinystr" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ - "chirp-types", - "http 0.2.12", - "prost 0.10.4", - "prost-types 0.10.1", - "serde", - "serde_json", - "thiserror 1.0.69", - "types-proto-build", - "uuid", + "displaydoc", + "zerovec", ] [[package]] -name = "types-proto-build" -version = "25.5.2" +name = "tinyvec" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" dependencies = [ - "heck 0.3.3", - "indoc 1.0.9", - "prost-build 0.11.9", - "protobuf-src", - "regex", - "schemac", - "serde", - "toml 0.7.8", + "tinyvec_macros", ] [[package]] -name = "ucd-trie" -version = "0.1.7" +name = "tinyvec_macros" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] -name = "unic-char-property" -version = "0.9.0" +name = "tokio" +version = "1.46.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" +checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17" dependencies = [ - "unic-char-range", + "backtrace", + "bytes", + "io-uring", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "slab", + "socket2 0.5.10", + "tokio-macros", + "tracing", + "windows-sys 0.52.0", ] [[package]] -name = "unic-char-range" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" - -[[package]] -name = "unic-common" -version = "0.9.0" +name = "tokio-cron-scheduler" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" +checksum = "6a5597b569b4712cf78aa0c9ae29742461b7bda1e49c2a5fdad1d79bf022f8f0" +dependencies = [ + "chrono", + "croner", + "num-derive", + "num-traits", + "tokio", + "tracing", + "uuid", +] [[package]] -name = "unic-ucd-ident" -version = "0.9.0" +name = "tokio-macros" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e230a37c0381caa9219d67cf063aa3a375ffed5bf541a452db16e744bdab6987" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-version", + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "unic-ucd-version" -version = "0.9.0" +name = "tokio-native-tls" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ - "unic-common", + "native-tls", + "tokio", ] [[package]] -name = "unicase" -version = "2.8.0" +name = "tokio-postgres" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" +checksum = "6c95d533c83082bb6490e0189acaa0bbeef9084e60471b696ca6988cd0541fb0" +dependencies = [ + "async-trait", + "byteorder", + "bytes", + "fallible-iterator", + "futures-channel", + "futures-util", + "log", + "parking_lot", + "percent-encoding", + "phf", + "pin-project-lite", + "postgres-protocol", + "postgres-types", + "rand 0.9.2", + "socket2 0.5.10", + "tokio", + "tokio-util", + "whoami", +] [[package]] -name = "unicode-bidi" -version = "0.3.17" +name = "tokio-retry" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" +checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f" +dependencies = [ + "pin-project", + "rand 0.8.5", + "tokio", +] [[package]] -name = "unicode-id" -version = "0.3.5" +name = "tokio-rustls" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10103c57044730945224467c09f71a4db0071c123a0648cc3e818913bde6b561" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.12", + "tokio", +] [[package]] -name = "unicode-id-start" -version = "1.3.1" +name = "tokio-rustls" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f322b60f6b9736017344fa0635d64be2f458fbc04eef65f6be22976dd1ffd5b" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +dependencies = [ + "rustls 0.23.29", + "tokio", +] [[package]] -name = "unicode-ident" -version = "1.0.14" +name = "tokio-stream" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] [[package]] -name = "unicode-normalization" -version = "0.1.24" +name = "tokio-tungstenite" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" dependencies = [ - "tinyvec", + "futures-util", + "log", + "tokio", + "tungstenite", ] [[package]] -name = "unicode-properties" -version = "0.1.3" +name = "tokio-util" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" +checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] [[package]] -name = "unicode-segmentation" -version = "1.12.0" +name = "toml_datetime" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" [[package]] -name = "unicode-width" -version = "0.1.14" +name = "toml_edit" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap 2.10.0", + "toml_datetime", + "winnow", +] [[package]] -name = "unicode-width" -version = "0.2.0" +name = "tonic" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" +checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" +dependencies = [ + "async-stream", + "async-trait", + "axum 0.7.9", + "base64 0.22.1", + "bytes", + "h2 0.4.11", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "hyper 1.6.0", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "prost", + "socket2 0.5.10", + "tokio", + "tokio-stream", + "tower 0.4.13", + "tower-layer", + "tower-service", + "tracing", +] [[package]] -name = "unicode-xid" -version = "0.2.6" +name = "tower" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap 1.9.3", + "pin-project", + "pin-project-lite", + "rand 0.8.5", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] [[package]] -name = "universal-hash" -version = "0.5.1" +name = "tower" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ - "crypto-common", - "subtle", + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", + "tracing", ] [[package]] -name = "unsafe-libyaml" -version = "0.2.11" +name = "tower-http" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "iri-string", + "pin-project-lite", + "tower 0.5.2", + "tower-layer", + "tower-service", + "tracing", +] [[package]] -name = "untrusted" -version = "0.7.1" +name = "tower-layer" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] -name = "untrusted" -version = "0.9.0" +name = "tower-service" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] -name = "unzip-n" -version = "0.1.2" +name = "tracing" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e7e85a0596447f0f2ac090e16bc4c516c6fe91771fb0c0ccf7fa3dae896b9c" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", ] [[package]] -name = "upload-complete" -version = "25.5.2" +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "prost 0.10.4", - "reqwest 0.11.27", - "rivet-operation", - "s3-util", - "sqlx", - "upload-get", - "upload-prepare", - "url", + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "upload-file-list" -version = "25.5.2" +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "prost 0.10.4", - "rivet-operation", - "sqlx", + "once_cell", + "valuable", ] [[package]] -name = "upload-get" -version = "25.5.2" +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "prost 0.10.4", - "rivet-operation", - "sqlx", - "upload-prepare", + "log", + "once_cell", + "tracing-core", ] [[package]] -name = "upload-list-for-user" -version = "25.5.2" +name = "tracing-logfmt" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1f47d22deb79c3f59fcf2a1f00f60cbdc05462bf17d1cd356c1fefa3f444bd" dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "prost 0.10.4", - "rivet-operation", - "sqlx", - "upload-prepare", + "nu-ansi-term 0.50.1", + "time", + "tracing", + "tracing-core", + "tracing-subscriber", ] [[package]] -name = "upload-prepare" -version = "25.5.2" +name = "tracing-opentelemetry" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721f2d2569dce9f3dfbbddee5906941e953bfcdf736a62da3377f5751650cc36" dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "prost 0.10.4", - "rand 0.8.5", - "reqwest 0.11.27", - "rivet-operation", - "s3-util", - "sqlx", - "upload-complete", - "upload-get", + "js-sys", + "once_cell", + "opentelemetry", + "opentelemetry_sdk", + "smallvec", + "tracing", + "tracing-core", + "tracing-log", + "tracing-subscriber", + "web-time", ] [[package]] -name = "upload-worker" -version = "25.5.2" +name = "tracing-serde" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" dependencies = [ - "chirp-client", - "chirp-worker", - "rivet-config", - "rivet-health-checks", - "rivet-metrics", - "rivet-runtime", - "s3-util", - "sqlx", - "upload-get", - "upload-prepare", + "serde", + "tracing-core", ] [[package]] -name = "ureq" -version = "2.10.1" +name = "tracing-slog" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" +checksum = "6ffd12d2d54fb99df994fde4e3320959e32208420bfe375a664c5d8cd894a23b" dependencies = [ - "base64 0.22.1", - "flate2", - "log", "once_cell", - "rustls 0.23.25", - "rustls-pki-types", - "url", - "webpki-roots 0.26.7", + "slog", + "tracing-core", ] [[package]] -name = "url" -version = "2.5.4" +name = "tracing-subscriber" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ - "form_urlencoded", - "idna 1.0.3", - "percent-encoding", + "matchers", + "nu-ansi-term 0.46.0", + "once_cell", + "regex", "serde", + "serde_json", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", + "tracing-serde", ] [[package]] -name = "urlencoding" -version = "2.1.3" +name = "try-lock" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] -name = "urlpattern" -version = "0.3.0" +name = "tungstenite" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70acd30e3aa1450bc2eece896ce2ad0d178e9c079493819301573dae3c37ba6d" +checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" dependencies = [ - "regex", - "serde", - "unic-ucd-ident", - "url", + "bytes", + "data-encoding", + "http 1.3.1", + "httparse", + "log", + "rand 0.9.2", + "sha1", + "thiserror 2.0.12", + "utf-8", ] [[package]] -name = "user" -version = "25.5.2" -dependencies = [ - "chirp-workflow", - "cluster", - "linode", - "rivet-config", - "server-spec", -] +name = "twox-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b907da542cbced5261bd3256de1b3a1bf340a3d37f93425a07362a1d687de56" [[package]] -name = "user-avatar-upload-complete" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-user", - "prost 0.10.4", - "reqwest 0.11.27", - "rivet-operation", - "sqlx", - "upload-complete", - "upload-get", - "upload-prepare", -] +name = "typenum" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] -name = "user-delete-pending" -version = "25.5.2" +name = "udb-util" +version = "0.0.1" dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", + "anyhow", + "async-trait", "futures-util", - "indoc 1.0.9", "lazy_static", - "prost 0.10.4", - "rivet-config", - "rivet-connection", - "rivet-operation", - "rivet-pools", - "rivet-runtime", + "rivet-metrics", "tokio", "tracing", - "tracing-logfmt", - "tracing-subscriber", + "universaldb", ] [[package]] -name = "user-get" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-user", - "prost 0.10.4", - "rand 0.8.5", - "rivet-operation", - "sqlx", - "upload-file-list", - "upload-get", -] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] -name = "user-identity-create" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "email-address-parser", - "faker-user", - "prost 0.10.4", - "rivet-operation", -] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] -name = "user-identity-delete" -version = "25.5.2" +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ - "chirp-client", - "chirp-worker", - "faker-user", - "prost 0.10.4", - "rivet-operation", - "sqlx", - "user-identity-create", + "tinyvec", ] [[package]] -name = "user-identity-get" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-user", - "prost 0.10.4", - "rivet-config", - "rivet-operation", - "sqlx", - "user-get", - "user-identity-create", -] +name = "unicode-properties" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] -name = "user-pending-delete-toggle" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-user", - "prost 0.10.4", - "rivet-operation", - "sqlx", - "user-identity-create", - "user-identity-get", -] +name = "unicode-width" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" [[package]] -name = "user-profile-validate" -version = "25.5.2" +name = "universaldb" +version = "0.0.1" dependencies = [ - "chirp-client", - "chirp-worker", - "faker-user", - "prost 0.10.4", - "rivet-operation", - "sqlx", - "user-get", + "anyhow", + "async-trait", + "deadpool-postgres", + "foundationdb-tuple", + "futures-util", + "lazy_static", + "rand 0.8.5", + "rivet-config", + "rivet-env", + "rivet-pools", + "rivet-test-deps-docker", + "rocksdb", + "serde", + "tempfile", + "tokio", + "tokio-postgres", + "tracing", + "tracing-subscriber", + "udb-util", + "uuid", ] [[package]] -name = "user-resolve-email" -version = "25.5.2" +name = "universalpubsub" +version = "0.0.1" dependencies = [ - "chirp-client", - "chirp-worker", - "faker-user", - "prost 0.10.4", - "rivet-operation", - "sqlx", - "user-identity-create", + "anyhow", + "async-nats", + "async-trait", + "base64 0.22.1", + "deadpool-postgres", + "futures-util", + "rivet-config", + "rivet-env", + "rivet-error", + "rivet-test-deps-docker", + "serde", + "serde_json", + "sha2", + "tempfile", + "tokio", + "tokio-postgres", + "tracing", + "tracing-subscriber", + "uuid", ] [[package]] -name = "user-team-list" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "prost 0.10.4", - "rivet-operation", - "sqlx", -] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] -name = "user-token-create" -version = "25.5.2" -dependencies = [ - "chirp-client", - "chirp-worker", - "faker-user", - "prost 0.10.4", - "rivet-operation", - "sqlx", - "token-create", -] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] -name = "user-worker" -version = "25.5.2" +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ - "chirp-client", - "chirp-worker", - "chrono", - "faker-user", - "game-get", - "game-namespace-get", - "lazy_static", - "rivet-config", - "rivet-convert", - "rivet-health-checks", - "rivet-metrics", - "rivet-runtime", - "team-get", - "team-member-list", - "upload-get", - "upload-list-for-user", - "upload-prepare", - "user-get", - "user-identity-delete", - "user-profile-validate", - "user-team-list", + "form_urlencoded", + "idna", + "percent-encoding", + "serde", ] [[package]] @@ -17112,12 +6087,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -17131,65 +6100,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] -name = "uuid" -version = "1.16.0" +name = "utoipa" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" +checksum = "2fcc29c80c21c31608227e0912b2d7fddba57ad76b606890627ba8ee7964e993" dependencies = [ - "getrandom 0.3.2", - "rand 0.9.0", + "indexmap 2.10.0", "serde", + "serde_json", + "utoipa-gen", ] [[package]] -name = "v8" -version = "130.0.4" +name = "utoipa-gen" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b61316a57fcd7e5f3840fe085f13e6dfd37e92d73b040033d2f598c7a1984c3" +checksum = "6d79d08d92ab8af4c5e8a6da20c47ae3f61a0f1dabc1997cdf2d082b757ca08b" dependencies = [ - "bindgen 0.70.1", - "bitflags 2.6.0", - "fslock", - "gzip-header", - "home", - "miniz_oxide 0.7.4", - "once_cell", - "paste", - "which 6.0.3", + "proc-macro2", + "quote", + "syn 2.0.104", + "uuid", ] [[package]] -name = "v8_valueserializer" -version = "0.1.1" +name = "uuid" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97599c400fc79925922b58303e98fcb8fa88f573379a08ddb652e72cbd2e70f6" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" dependencies = [ - "bitflags 2.6.0", - "encoding_rs", - "indexmap 2.7.0", - "num-bigint", + "getrandom 0.3.3", + "js-sys", "serde", - "thiserror 1.0.69", - "wtf8", + "wasm-bindgen", ] [[package]] name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - -[[package]] -name = "value-trait" -version = "0.10.1" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9170e001f458781e92711d2ad666110f153e4e50bfd5cbd02db6547625714187" -dependencies = [ - "float-cmp", - "halfbrown", - "itoa 1.0.14", - "ryu", -] +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "vcpkg" @@ -17199,25 +6149,21 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "vergen" -version = "9.0.4" +version = "9.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0d2f179f8075b805a43a2a21728a46f0cc2921b3c58695b28fa8817e103cd9a" +checksum = "6b2bf58be11fc9414104c6d3a2e464163db5ef74b12296bda593cac37b6e4777" dependencies = [ "anyhow", - "cargo_metadata", "derive_builder 0.20.2", - "regex", - "rustc_version 0.4.1", "rustversion", - "time 0.3.37", "vergen-lib", ] [[package]] name = "vergen-lib" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0c767e6751c09fc85cde58722cf2f1007e80e4c8d5a4321fc90d83dc54ca147" +checksum = "9b07e6010c0f3e59fcb164e0163834597da68d1f864e2b8ca49f74de01e9c166" dependencies = [ "anyhow", "derive_builder 0.20.2", @@ -17231,10 +6177,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] -name = "vsimd" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" +name = "versioned-data-util" +version = "0.0.1" +dependencies = [ + "anyhow", + "serde", + "serde_bare", +] [[package]] name = "vte" @@ -17242,20 +6191,11 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6cbce692ab4ca2f1f3047fcf732430249c0e971bfdd2b234cf2c47ad93af5983" dependencies = [ - "arrayvec 0.5.2", + "arrayvec", "utf8parse", "vte_generate_state_changes", ] -[[package]] -name = "vte" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "231fdcd7ef3037e8330d8e17e61011a2c244126acc0a982f4040ac3f9f0bc077" -dependencies = [ - "memchr", -] - [[package]] name = "vte_generate_state_changes" version = "0.1.2" @@ -17266,25 +6206,6 @@ dependencies = [ "quote", ] -[[package]] -name = "wait-timeout" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" -dependencies = [ - "libc", -] - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - [[package]] name = "want" version = "0.3.1" @@ -17296,15 +6217,9 @@ dependencies = [ [[package]] name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" @@ -17323,332 +6238,116 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.97" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c" -dependencies = [ - "cfg-if", - "once_cell", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.97" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.90", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.47" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dfaf8f50e5f293737ee323940c7d8b08a66a95a419223d9f41610ca08b0833d" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", - "js-sys", "once_cell", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.97" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.97" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.97" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49" - -[[package]] -name = "wasm-streams" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" -dependencies = [ - "futures-util", - "js-sys", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "wasm_dep_analyzer" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f270206a91783fd90625c8bb0d8fbd459d0b1d1bf209b656f713f01ae7c04b8" -dependencies = [ - "thiserror 1.0.69", -] - -[[package]] -name = "web-sys" -version = "0.3.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a98bc3c33f0fe7e59ad7cd041b89034fa82a7c2d4365ca538dda6cdaf513863c" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webbrowser" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea9fe1ebb156110ff855242c1101df158b822487e4957b0556d9ffce9db0f535" -dependencies = [ - "block2", - "core-foundation 0.10.0", - "home", - "jni", - "log", - "ndk-context", - "objc2", - "objc2-foundation", - "url", - "web-sys", -] - -[[package]] -name = "webpki" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" -dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", -] - -[[package]] -name = "webpki" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" -dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", -] - -[[package]] -name = "webpki-root-certs" -version = "0.26.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cd5da49bdf1f30054cfe0b8ce2958b8fbeb67c4d82c8967a598af481bef255c" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "webpki-roots" -version = "0.22.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" -dependencies = [ - "webpki 0.22.4", -] - -[[package]] -name = "webpki-roots" -version = "0.25.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" - -[[package]] -name = "webpki-roots" -version = "0.26.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" -dependencies = [ - "rustls-pki-types", + "rustversion", + "wasm-bindgen-macro", ] [[package]] -name = "wgpu-core" -version = "0.21.1" +name = "wasm-bindgen-backend" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50819ab545b867d8a454d1d756b90cd5f15da1f2943334ca314af10583c9d39" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ - "arrayvec 0.7.6", - "bit-vec", - "bitflags 2.6.0", - "cfg_aliases 0.1.1", - "codespan-reporting", - "document-features", - "indexmap 2.7.0", + "bumpalo", "log", - "naga", - "once_cell", - "parking_lot 0.12.3", - "profiling", - "raw-window-handle", - "ron", - "rustc-hash 1.1.0", - "serde", - "smallvec", - "thiserror 1.0.69", - "web-sys", - "wgpu-hal", - "wgpu-types", + "proc-macro2", + "quote", + "syn 2.0.104", + "wasm-bindgen-shared", ] [[package]] -name = "wgpu-hal" -version = "0.21.1" +name = "wasm-bindgen-futures" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "172e490a87295564f3fcc0f165798d87386f6231b04d4548bca458cbbfd63222" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ - "android_system_properties", - "arrayvec 0.7.6", - "ash", - "bit-set", - "bitflags 2.6.0", - "block", - "cfg_aliases 0.1.1", - "core-graphics-types", - "d3d12", - "glow", - "glutin_wgl_sys", - "gpu-alloc", - "gpu-descriptor", + "cfg-if", "js-sys", - "khronos-egl", - "libc", - "libloading 0.8.6", - "log", - "metal", - "naga", - "ndk-sys", - "objc", "once_cell", - "parking_lot 0.12.3", - "profiling", - "range-alloc", - "raw-window-handle", - "rustc-hash 1.1.0", - "smallvec", - "thiserror 1.0.69", "wasm-bindgen", "web-sys", - "wgpu-types", - "winapi", ] [[package]] -name = "wgpu-types" -version = "0.20.0" +name = "wasm-bindgen-macro" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1353d9a46bff7f955a680577f34c69122628cc2076e1d6f3a9be6ef00ae793ef" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ - "bitflags 2.6.0", - "js-sys", - "serde", - "web-sys", + "quote", + "wasm-bindgen-macro-support", ] [[package]] -name = "which" -version = "4.4.2" +name = "wasm-bindgen-macro-support" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ - "either", - "home", - "once_cell", - "rustix", + "proc-macro2", + "quote", + "syn 2.0.104", + "wasm-bindgen-backend", + "wasm-bindgen-shared", ] [[package]] -name = "which" -version = "5.0.0" +name = "wasm-bindgen-shared" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bf3ea8596f3a0dd5980b46430f2058dfe2c36a27ccfbb1845d6fbfcd9ba6e14" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" dependencies = [ - "either", - "home", - "once_cell", - "rustix", - "windows-sys 0.48.0", + "unicode-ident", ] [[package]] -name = "which" -version = "6.0.3" +name = "web-sys" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ - "either", - "home", - "rustix", - "winsafe", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", ] [[package]] name = "whoami" -version = "1.5.2" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" +checksum = "6994d13118ab492c3c80c1f81928718159254c53c472bf9ce36f8dae4add02a7" dependencies = [ - "redox_syscall 0.5.7", + "redox_syscall", "wasite", "web-sys", ] [[package]] name = "wide" -version = "0.7.32" +version = "0.7.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41b5576b9a81633f3e8df296ce0063042a73507636cbe956c61133dd7034ab22" +checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03" dependencies = [ "bytemuck", "safe_arch", ] -[[package]] -name = "widestring" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" - [[package]] name = "winapi" version = "0.3.9" @@ -17665,15 +6364,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys 0.59.0", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -17682,129 +6372,142 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.48.0" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" dependencies = [ - "windows-targets 0.48.5", + "windows-core 0.58.0", + "windows-targets 0.52.6", ] [[package]] name = "windows" -version = "0.57.0" +version = "0.61.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" dependencies = [ - "windows-core 0.57.0", - "windows-targets 0.52.6", + "windows-collections", + "windows-core 0.61.2", + "windows-future", + "windows-link", + "windows-numerics", ] [[package]] -name = "windows" -version = "0.58.0" +name = "windows-collections" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" dependencies = [ - "windows-core 0.58.0", - "windows-targets 0.52.6", + "windows-core 0.61.2", ] [[package]] name = "windows-core" -version = "0.52.0" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" dependencies = [ + "windows-implement 0.58.0", + "windows-interface 0.58.0", + "windows-result 0.2.0", + "windows-strings 0.1.0", "windows-targets 0.52.6", ] [[package]] name = "windows-core" -version = "0.57.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ - "windows-implement 0.57.0", - "windows-interface 0.57.0", - "windows-result 0.1.2", - "windows-targets 0.52.6", + "windows-implement 0.60.0", + "windows-interface 0.59.1", + "windows-link", + "windows-result 0.3.4", + "windows-strings 0.4.2", ] [[package]] -name = "windows-core" -version = "0.58.0" +name = "windows-future" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" dependencies = [ - "windows-implement 0.58.0", - "windows-interface 0.58.0", - "windows-result 0.2.0", - "windows-strings", - "windows-targets 0.52.6", + "windows-core 0.61.2", + "windows-link", + "windows-threading", ] [[package]] name = "windows-implement" -version = "0.57.0" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.104", ] [[package]] name = "windows-implement" -version = "0.58.0" +version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.104", ] [[package]] name = "windows-interface" -version = "0.57.0" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.104", ] [[package]] name = "windows-interface" -version = "0.58.0" +version = "0.59.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.104", ] [[package]] -name = "windows-registry" +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-numerics" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ - "windows-result 0.2.0", - "windows-strings", - "windows-targets 0.52.6", + "windows-core 0.61.2", + "windows-link", ] [[package]] -name = "windows-result" -version = "0.1.2" +name = "windows-registry" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" dependencies = [ - "windows-targets 0.52.6", + "windows-link", + "windows-result 0.3.4", + "windows-strings 0.4.2", ] [[package]] @@ -17816,6 +6519,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-strings" version = "0.1.0" @@ -17827,12 +6539,12 @@ dependencies = [ ] [[package]] -name = "windows-sys" -version = "0.45.0" +name = "windows-strings" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-targets 0.42.2", + "windows-link", ] [[package]] @@ -17863,18 +6575,12 @@ dependencies = [ ] [[package]] -name = "windows-targets" -version = "0.42.2" +name = "windows-sys" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets 0.53.2", ] [[package]] @@ -17901,7 +6607,7 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", @@ -17909,10 +6615,29 @@ dependencies = [ ] [[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" +name = "windows-targets" +version = "0.53.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows-threading" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link", +] [[package]] name = "windows_aarch64_gnullvm" @@ -17927,10 +6652,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" +name = "windows_aarch64_gnullvm" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" [[package]] name = "windows_aarch64_msvc" @@ -17945,10 +6670,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] -name = "windows_i686_gnu" -version = "0.42.2" +name = "windows_aarch64_msvc" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" [[package]] name = "windows_i686_gnu" @@ -17962,6 +6687,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" @@ -17969,10 +6700,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] -name = "windows_i686_msvc" -version = "0.42.2" +name = "windows_i686_gnullvm" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" [[package]] name = "windows_i686_msvc" @@ -17987,10 +6718,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" +name = "windows_i686_msvc" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" [[package]] name = "windows_x86_64_gnu" @@ -18005,10 +6736,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" +name = "windows_x86_64_gnu" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" [[package]] name = "windows_x86_64_gnullvm" @@ -18023,10 +6754,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" +name = "windows_x86_64_gnullvm" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" [[package]] name = "windows_x86_64_msvc" @@ -18041,117 +6772,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] -name = "winnow" -version = "0.5.40" +name = "windows_x86_64_msvc" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] -name = "winreg" -version = "0.50.0" +name = "winnow" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" dependencies = [ - "cfg-if", - "windows-sys 0.48.0", + "memchr", ] -[[package]] -name = "winsafe" -version = "0.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" - [[package]] name = "wit-bindgen-rt" version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "bitflags 2.6.0", + "bitflags", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - [[package]] name = "writeable" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" - -[[package]] -name = "wtf8" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c01ae8492c38f52376efd3a17d0994b6bcf3df1e39c0226d458b7d81670b2a06" - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - -[[package]] -name = "x25519-dalek" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" -dependencies = [ - "curve25519-dalek", - "rand_core 0.6.4", - "serde", - "zeroize", -] - -[[package]] -name = "x509-parser" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7069fba5b66b9193bd2c5d3d4ff12b839118f6bcbef5328efafafb5395cf63da" -dependencies = [ - "asn1-rs", - "data-encoding", - "der-parser", - "lazy_static", - "nom 7.1.3", - "oid-registry", - "rusticata-macros", - "thiserror 1.0.69", - "time 0.3.37", -] - -[[package]] -name = "xattr" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" -dependencies = [ - "libc", - "linux-raw-sys", - "rustix", -] - -[[package]] -name = "xml-rs" -version = "0.8.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea8b391c9a790b496184c29f7f93b9ed5b16abb306c05415b68bcc16e4d06432" - -[[package]] -name = "xmlparser" -version = "0.13.6" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "yaml-rust2" @@ -18161,7 +6809,7 @@ checksum = "8902160c4e6f2fb145dbe9d6760a75e3c9522d8bf796ed7047c85919ac7115f8" dependencies = [ "arraydeque", "encoding_rs", - "hashlink 0.8.4", + "hashlink", ] [[package]] @@ -18172,9 +6820,9 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "yoke" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" dependencies = [ "serde", "stable_deref_trait", @@ -18184,76 +6832,55 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", - "synstructure 0.13.1", -] - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive 0.7.35", + "syn 2.0.104", + "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" -dependencies = [ - "zerocopy-derive 0.8.24", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", + "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.24" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.104", ] [[package]] name = "zerofrom" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", - "synstructure 0.13.1", + "syn 2.0.104", + "synstructure", ] [[package]] @@ -18261,26 +6888,23 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -dependencies = [ - "zeroize_derive", -] [[package]] -name = "zeroize_derive" -version = "1.4.2" +name = "zerotrie" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", + "displaydoc", + "yoke", + "zerofrom", ] [[package]] name = "zerovec" -version = "0.10.4" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" dependencies = [ "yoke", "zerofrom", @@ -18289,25 +6913,21 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.104", ] [[package]] -name = "zip" -version = "0.5.13" +name = "zstd-sys" +version = "2.0.15+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ab48844d61251bb3835145c521d88aa4031d7139e8485990f60ca911fa0815" +checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" dependencies = [ - "byteorder", - "bzip2", - "crc32fast", - "flate2", - "thiserror 1.0.69", - "time 0.1.45", + "cc", + "pkg-config", ] diff --git a/Cargo.toml b/Cargo.toml index 42349bff27..487c15a683 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,127 +1,264 @@ [workspace] resolver = "2" -members = ["packages/common/api-helper/build","packages/common/api-helper/macros","packages/common/cache/build","packages/common/cache/result","packages/common/chirp-workflow/core","packages/common/chirp-workflow/macros","packages/common/chirp/client","packages/common/chirp/metrics","packages/common/chirp/perf","packages/common/chirp/types","packages/common/chirp/worker","packages/common/chirp/worker-attributes","packages/common/claims","packages/common/clickhouse-inserter","packages/common/clickhouse-user-query","packages/common/config","packages/common/connection","packages/common/convert","packages/common/deno-embed","packages/common/env","packages/common/fdb-util","packages/common/formatted-error","packages/common/global-error","packages/common/health-checks","packages/common/kv-str","packages/common/logs","packages/common/metrics","packages/common/migrate","packages/common/nomad-util","packages/common/operation/core","packages/common/operation/macros","packages/common/pools","packages/common/redis-util","packages/common/runtime","packages/common/s3-util","packages/common/schemac","packages/common/server-cli","packages/common/service-discovery","packages/common/service-manager","packages/common/smithy-output/api-auth/rust","packages/common/smithy-output/api-auth/rust-server","packages/common/smithy-output/api-cf-verification/rust","packages/common/smithy-output/api-cf-verification/rust-server","packages/common/smithy-output/api-cloud/rust","packages/common/smithy-output/api-cloud/rust-server","packages/common/smithy-output/api-group/rust","packages/common/smithy-output/api-group/rust-server","packages/common/smithy-output/api-identity/rust","packages/common/smithy-output/api-identity/rust-server","packages/common/smithy-output/api-job/rust","packages/common/smithy-output/api-job/rust-server","packages/common/smithy-output/api-kv/rust","packages/common/smithy-output/api-kv/rust-server","packages/common/smithy-output/api-matchmaker/rust","packages/common/smithy-output/api-matchmaker/rust-server","packages/common/smithy-output/api-party/rust","packages/common/smithy-output/api-party/rust-server","packages/common/smithy-output/api-portal/rust","packages/common/smithy-output/api-portal/rust-server","packages/common/smithy-output/api-status/rust","packages/common/smithy-output/api-status/rust-server","packages/common/smithy-output/api-traefik-provider/rust","packages/common/smithy-output/api-traefik-provider/rust-server","packages/common/test","packages/common/test-images","packages/common/types-proto/build","packages/common/types-proto/core","packages/common/util/core","packages/common/util/macros","packages/common/util/search","packages/core/api/actor","packages/core/api/auth","packages/core/api/cf-verification","packages/core/api/cloud","packages/core/api/games","packages/core/api/group","packages/core/api/identity","packages/core/api/intercom","packages/core/api/job","packages/core/api/matchmaker","packages/core/api/monolith-edge","packages/core/api/monolith-public","packages/core/api/portal","packages/core/api/provision","packages/core/api/status","packages/core/api/traefik-provider","packages/core/api/ui","packages/core/infra/legacy/job-runner","packages/core/infra/schema-generator","packages/core/infra/server","packages/core/services/build","packages/core/services/build/ops/create","packages/core/services/build/ops/get","packages/core/services/build/ops/list-for-env","packages/core/services/build/ops/list-for-game","packages/core/services/build/standalone/default-create","packages/core/services/build/util","packages/core/services/captcha/ops/hcaptcha-config-get","packages/core/services/captcha/ops/hcaptcha-verify","packages/core/services/captcha/ops/request","packages/core/services/captcha/ops/turnstile-config-get","packages/core/services/captcha/ops/turnstile-verify","packages/core/services/captcha/ops/verify","packages/core/services/captcha/util","packages/core/services/cdn/ops/namespace-auth-user-remove","packages/core/services/cdn/ops/namespace-auth-user-update","packages/core/services/cdn/ops/namespace-create","packages/core/services/cdn/ops/namespace-domain-create","packages/core/services/cdn/ops/namespace-domain-remove","packages/core/services/cdn/ops/namespace-get","packages/core/services/cdn/ops/namespace-resolve-domain","packages/core/services/cdn/ops/ns-auth-type-set","packages/core/services/cdn/ops/ns-enable-domain-public-auth-set","packages/core/services/cdn/ops/site-create","packages/core/services/cdn/ops/site-get","packages/core/services/cdn/ops/site-list-for-game","packages/core/services/cdn/ops/version-get","packages/core/services/cdn/ops/version-prepare","packages/core/services/cdn/ops/version-publish","packages/core/services/cdn/util","packages/core/services/cdn/worker","packages/core/services/cf-custom-hostname/ops/get","packages/core/services/cf-custom-hostname/ops/list-for-namespace-id","packages/core/services/cf-custom-hostname/ops/resolve-hostname","packages/core/services/cf-custom-hostname/worker","packages/core/services/cloud/ops/device-link-create","packages/core/services/cloud/ops/game-config-create","packages/core/services/cloud/ops/game-config-get","packages/core/services/cloud/ops/game-token-create","packages/core/services/cloud/ops/namespace-create","packages/core/services/cloud/ops/namespace-get","packages/core/services/cloud/ops/namespace-token-development-create","packages/core/services/cloud/ops/namespace-token-public-create","packages/core/services/cloud/ops/version-get","packages/core/services/cloud/ops/version-publish","packages/core/services/cloud/standalone/default-create","packages/core/services/cloud/worker","packages/core/services/cluster","packages/core/services/cluster/standalone/datacenter-tls-renew","packages/core/services/cluster/standalone/default-update","packages/core/services/cluster/standalone/gc","packages/core/services/cluster/standalone/metrics-publish","packages/core/services/custom-user-avatar/ops/list-for-game","packages/core/services/custom-user-avatar/ops/upload-complete","packages/core/services/debug/ops/email-res","packages/core/services/dynamic-config","packages/core/services/email-verification/ops/complete","packages/core/services/email-verification/ops/create","packages/core/services/email/ops/send","packages/core/services/external/ops/request-validate","packages/core/services/external/worker","packages/core/services/faker/ops/build","packages/core/services/faker/ops/cdn-site","packages/core/services/faker/ops/game","packages/core/services/faker/ops/game-namespace","packages/core/services/faker/ops/game-version","packages/core/services/faker/ops/job-run","packages/core/services/faker/ops/job-template","packages/core/services/faker/ops/mm-lobby","packages/core/services/faker/ops/mm-lobby-row","packages/core/services/faker/ops/mm-player","packages/core/services/faker/ops/region","packages/core/services/faker/ops/team","packages/core/services/faker/ops/user","packages/core/services/game/ops/banner-upload-complete","packages/core/services/game/ops/create","packages/core/services/game/ops/get","packages/core/services/game/ops/list-all","packages/core/services/game/ops/list-for-team","packages/core/services/game/ops/logo-upload-complete","packages/core/services/game/ops/namespace-create","packages/core/services/game/ops/namespace-get","packages/core/services/game/ops/namespace-list","packages/core/services/game/ops/namespace-resolve-name-id","packages/core/services/game/ops/namespace-resolve-url","packages/core/services/game/ops/namespace-validate","packages/core/services/game/ops/namespace-version-history-list","packages/core/services/game/ops/namespace-version-set","packages/core/services/game/ops/recommend","packages/core/services/game/ops/resolve-name-id","packages/core/services/game/ops/resolve-namespace-id","packages/core/services/game/ops/token-development-validate","packages/core/services/game/ops/validate","packages/core/services/game/ops/version-create","packages/core/services/game/ops/version-get","packages/core/services/game/ops/version-list","packages/core/services/game/ops/version-validate","packages/core/services/guard","packages/core/services/ip/ops/info","packages/core/services/job-log/ops/read","packages/core/services/job-log/worker","packages/core/services/job-run","packages/core/services/job/standalone/gc","packages/core/services/job/util","packages/core/services/linode","packages/core/services/linode/standalone/gc","packages/core/services/load-test/standalone/api-cloud","packages/core/services/load-test/standalone/mm","packages/core/services/load-test/standalone/mm-sustain","packages/core/services/load-test/standalone/sqlx","packages/core/services/load-test/standalone/watch-requests","packages/core/services/mm-config/ops/game-get","packages/core/services/mm-config/ops/game-upsert","packages/core/services/mm-config/ops/lobby-group-get","packages/core/services/mm-config/ops/lobby-group-resolve-name-id","packages/core/services/mm-config/ops/lobby-group-resolve-version","packages/core/services/mm-config/ops/namespace-config-set","packages/core/services/mm-config/ops/namespace-config-validate","packages/core/services/mm-config/ops/namespace-create","packages/core/services/mm-config/ops/namespace-get","packages/core/services/mm-config/ops/version-get","packages/core/services/mm-config/ops/version-prepare","packages/core/services/mm-config/ops/version-publish","packages/core/services/mm/ops/dev-player-token-create","packages/core/services/mm/ops/lobby-find-fail","packages/core/services/mm/ops/lobby-find-lobby-query-list","packages/core/services/mm/ops/lobby-find-try-complete","packages/core/services/mm/ops/lobby-for-run-id","packages/core/services/mm/ops/lobby-get","packages/core/services/mm/ops/lobby-history","packages/core/services/mm/ops/lobby-idle-update","packages/core/services/mm/ops/lobby-list-for-namespace","packages/core/services/mm/ops/lobby-list-for-user-id","packages/core/services/mm/ops/lobby-player-count","packages/core/services/mm/ops/lobby-runtime-aggregate","packages/core/services/mm/ops/lobby-state-get","packages/core/services/mm/ops/player-count-for-namespace","packages/core/services/mm/ops/player-get","packages/core/services/mm/standalone/gc","packages/core/services/mm/util","packages/core/services/mm/worker","packages/core/services/monolith/standalone/worker","packages/core/services/monolith/standalone/workflow-worker","packages/core/services/nomad/standalone/monitor","packages/core/services/region/ops/get","packages/core/services/region/ops/list","packages/core/services/region/ops/list-for-game","packages/core/services/region/ops/recommend","packages/core/services/region/ops/resolve","packages/core/services/region/ops/resolve-for-game","packages/core/services/route","packages/core/services/server-spec","packages/core/services/team-invite/ops/get","packages/core/services/team-invite/worker","packages/core/services/team/ops/avatar-upload-complete","packages/core/services/team/ops/get","packages/core/services/team/ops/join-request-list","packages/core/services/team/ops/member-count","packages/core/services/team/ops/member-get","packages/core/services/team/ops/member-list","packages/core/services/team/ops/member-relationship-get","packages/core/services/team/ops/profile-validate","packages/core/services/team/ops/recommend","packages/core/services/team/ops/resolve-display-name","packages/core/services/team/ops/user-ban-get","packages/core/services/team/ops/user-ban-list","packages/core/services/team/ops/validate","packages/core/services/team/util","packages/core/services/team/worker","packages/core/services/telemetry/standalone/beacon","packages/core/services/tier","packages/core/services/token/ops/create","packages/core/services/token/ops/exchange","packages/core/services/token/ops/get","packages/core/services/token/ops/revoke","packages/core/services/upload/ops/complete","packages/core/services/upload/ops/file-list","packages/core/services/upload/ops/get","packages/core/services/upload/ops/list-for-user","packages/core/services/upload/ops/prepare","packages/core/services/upload/worker","packages/core/services/user","packages/core/services/user-identity/ops/create","packages/core/services/user-identity/ops/delete","packages/core/services/user-identity/ops/get","packages/core/services/user/ops/avatar-upload-complete","packages/core/services/user/ops/get","packages/core/services/user/ops/pending-delete-toggle","packages/core/services/user/ops/profile-validate","packages/core/services/user/ops/resolve-email","packages/core/services/user/ops/team-list","packages/core/services/user/ops/token-create","packages/core/services/user/standalone/delete-pending","packages/core/services/user/worker","packages/edge/api/actor","packages/edge/api/intercom","packages/edge/api/monolith-edge","packages/edge/api/monolith-public","packages/edge/api/traefik-provider","packages/edge/infra/client/actor-kv","packages/edge/infra/client/config","packages/edge/infra/client/container-runner","packages/edge/infra/client/echo","packages/edge/infra/client/isolate-v8-runner","packages/edge/infra/client/manager","packages/edge/infra/edge-server","packages/edge/infra/guard/core","packages/edge/infra/guard/server","packages/edge/services/monolith/standalone/workflow-worker","packages/edge/services/pegboard","packages/edge/services/pegboard/standalone/usage-metrics-publish","packages/edge/services/pegboard/standalone/ws","packages/toolchain/cli","packages/toolchain/js-utils-embed","packages/toolchain/toolchain","sdks/api/full/rust"] +members = ["packages/common/api-builder","packages/common/api-client","packages/common/api-types","packages/common/api-util","packages/common/cache/build","packages/common/cache/result","packages/common/clickhouse-inserter","packages/common/clickhouse-user-query","packages/common/config","packages/common/env","packages/common/error/core","packages/common/error/macros","packages/common/gasoline/core","packages/common/gasoline/macros","packages/common/logs","packages/common/metrics","packages/common/pools","packages/common/runtime","packages/common/service-manager","packages/common/test-deps","packages/common/test-deps-docker","packages/common/types","packages/common/udb-util","packages/common/universaldb","packages/common/universalpubsub","packages/common/util/core","packages/common/util/id","packages/common/versioned-data-util","packages/core/actor-kv","packages/core/api-peer","packages/core/api-public","packages/core/bootstrap","packages/core/dump-openapi","packages/core/guard/core","packages/core/guard/server","packages/core/pegboard-gateway","packages/core/pegboard-runner-ws","packages/core/pegboard-tunnel","packages/core/workflow-worker","packages/infra/engine","packages/services/epoxy","packages/services/namespace","packages/services/pegboard","sdks/rust/api-full","sdks/rust/api-runtime","sdks/rust/bare_gen","sdks/rust/epoxy-protocol","sdks/rust/key-data","sdks/rust/runner-protocol","sdks/rust/tunnel-protocol"] [workspace.package] -version = "25.5.3" -edition = "2021" +version = "0.0.1" +edition = "2024" authors = ["Rivet Gaming, LLC "] license = "Apache-2.0" [workspace.dependencies] -anyhow = "1.0.79" -dirs = "5.0" +anyhow = "1.0.82" +async-channel = "2.1.1" +async-nats = "0.33" +async-stream = "0.3" +async-trait = "0.1" +axum-test = "17" +base64 = "0.22" +bcrypt = "0.13.0" +bytes = "1.6.0" +cjson = "0.1" +colored_json = "5.0.0" +console-subscriber = "0.4" +dirs = "5.0.1" +divan = "0.1.17" +foundationdb-tuple = "0.9.1" +fs_extra = "1.3.0" +futures = "0.3.30" +futures-util = "0.3" +glob = "0.3.1" +governor = "0.6" +heck = "0.5" hex = "0.4" +http-body = "1.0.0" +http-body-util = "0.1.1" +hyper-tls = "0.5.0" +hyper-tungstenite = "0.17.0" +include_dir = "0.7.4" +indoc = "2.0.5" +itertools = "0.14.0" json5 = "0.4.1" -tracing = "0.1" +lazy_static = "1.4" +libc = "0.2" +lz4_flex = "0.11.3" +maplit = "1.0.2" +md5 = "0.7.0" +once_cell = "1.20.2" +opentelemetry-appender-tracing = "0.28.1" +papaya = "0.2.1" +pest_derive = "2.7" +portpicker = "0.1" +prettyplease = "0.2" +protobuf = "2.28" +quote = "1.0" +rand = "0.8" +regex = "1.4" +rstest = "0.26.1" +rustls-pemfile = "2.2.0" +rustyline = "15.0.0" +serde_bare = "0.5.0" +serde_yaml = "0.9.34" +sha2 = "0.10" +slog = "2.7" +slog-async = "2.8" +slog-term = "2.9" +statrs = "0.18" +tabled = "0.17.0" +tempfile = "3.13.0" +thiserror = "1.0.64" +tokio-cron-scheduler = "0.13.0" +tokio-native-tls = "0.3.1" +tokio-stream = "0.1.15" +tokio-tungstenite = "0.26.0" +tokio-util = "0.7" +tower = "0.5" +tracing = "0.1.40" +tracing-core = "0.1" +tracing-opentelemetry = "0.29" +tracing-slog = "0.2" +vergen = "9.0.4" + +[workspace.dependencies.windows] +version = "0.58" +features = [ + "Win32", + "Win32_Storage", + "Win32_Storage_FileSystem", + "Win32_System", + "Win32_System_Console", + "Win32_Security", +] + +[workspace.dependencies.pest] +version = "2.7" + +[workspace.dependencies.rocksdb] +version = "0.24" +features = ["multi-threaded-cf"] + +[workspace.dependencies.hyper-util] +version = "0.1.10" +features = ["full"] + +[workspace.dependencies.rustls] +version = "0.23.25" +default-features = false +features = ["ring", "std", "logging"] -[workspace.dependencies.tokio] -version = "1.44.0" -features = ["full","tracing"] +[workspace.dependencies.tokio-rustls] +version = "0.26.2" +default-features = false +features = ["ring", "logging"] + +[workspace.dependencies.utoipa] +version = "5.4.0" +features = ["uuid"] + +[workspace.dependencies.axum] +version = "0.8" +features = ["http2"] + +[workspace.dependencies.tower-http] +version = "0.6" +features = ["cors","trace"] + +[workspace.dependencies.serde_json] +version = "1.0.128" +features = ["raw_value"] [workspace.dependencies.nix] version = "0.30" default-features = false features = ["fs","user","signal"] -[workspace.dependencies.tracing-logfmt] -version = "0.3" -features = ["ansi_logs"] +[workspace.dependencies.chrono] +version = "0.4.38" +features = ["now"] -[workspace.dependencies.tracing-subscriber] -version = "0.3" -default-features = false -features = ["ansi","fmt","json"] +[workspace.dependencies.clap] +version = "4.3" +features = ["derive"] + +[workspace.dependencies.rivet-term] +git = "https://github.com/rivet-gg/rivet-term" +rev = "55e328470b68c557fb9bc8298369f90182d35b6d" + +[workspace.dependencies.clickhouse] +version = "0.11.2" +features = ["uuid"] -[workspace.dependencies.sqlx] -git = "https://github.com/rivet-gg/sqlx" -rev = "aeeae14fe7a05aa05e72a4dad59998b8bd72ad3a" +[workspace.dependencies.config] +version = "0.14.0" default-features = false +features = ["async","json","yaml"] -[workspace.dependencies.foundationdb] -version = "0.9.1" -features = ["fdb-7_1","embedded-fdb-include"] +[workspace.dependencies.hyper] +version = "0.14" +features = ["server","http1","tcp"] -[workspace.dependencies.futures-util] -version = "0.3" +[workspace.dependencies.indexmap] +version = "2.0" +features = ["serde"] -[workspace.dependencies.nomad_client] -git = "https://github.com/rivet-gg/nomad-client" -rev = "abb66bf" +[workspace.dependencies.ipnet] +version = "2.10.1" +features = ["serde"] -[workspace.dependencies.nomad_client_new] -git = "https://github.com/rivet-gg/nomad-client" -rev = "abb66bf" -package = "nomad_client" +[workspace.dependencies.moka] +version = "0.12" +features = ["future"] -[workspace.dependencies.async-posthog] -git = "https://github.com/rivet-gg/posthog-rs" -rev = "ef4e80e" +[workspace.dependencies.opentelemetry] +version = "0.28" +features = ["trace","metrics","logs"] -[workspace.dependencies.cloudflare] -git = "https://github.com/LSilent/cloudflare-rs" -rev = "b2c6f366ee68a7956fb69dd4f39357b3c184bd15" +[workspace.dependencies.opentelemetry-otlp] +version = "0.28" +features = ["trace","metrics","logs","grpc-tonic"] -[workspace.dependencies.rivet-term] -git = "https://github.com/rivet-gg/rivet-term" -rev = "55e328470b68c557fb9bc8298369f90182d35b6d" +[workspace.dependencies.opentelemetry_sdk] +version = "0.28" +features = ["trace","metrics","logs"] -[workspace.dependencies.redis] -git = "https://github.com/rivet-gg/redis-rs" -rev = "ac3e27f" -default-features = false +[workspace.dependencies.opentelemetry-semantic-conventions] +version = "0.28" +features = ["semconv_experimental"] -[workspace.dependencies.serde_array_query] -git = "https://github.com/rivet-gg/serde_array_query" -rev = "b9f8bfa" +[workspace.dependencies.opentelemetry-stdout] +version = "0.28.0" +features = ["trace","metrics","logs"] -[workspace.dependencies.deno_core] -git = "https://github.com/rivet-gg/deno_core" -rev = "8a313913fa73d58f4f9532565b0084e723bc34ad" +[workspace.dependencies.proc-macro2] +version = "1.0" +features = ["span-locations"] -[workspace.dependencies.deno_runtime] -git = "https://github.com/rivet-gg/deno" -rev = "a6903d67063e07b82836399f63c7a0fa5be8bf56" +[workspace.dependencies.reqwest] +version = "0.12.22" +features = ["json"] -[workspace.dependencies.api-helper] -path = "packages/common/api-helper/build" +[workspace.dependencies.schemars] +version = "0.8.21" +features = ["url","uuid1"] -[workspace.dependencies.api-helper-macros] -path = "packages/common/api-helper/macros" +[workspace.dependencies.serde] +version = "1.0" +features = ["derive"] -[workspace.dependencies.rivet-cache] -path = "packages/common/cache/build" +[workspace.dependencies.strum] +version = "0.26.3" +features = ["derive"] -[workspace.dependencies.rivet-cache-result] -path = "packages/common/cache/result" +[workspace.dependencies.syn] +version = "2.0" +features = ["full","extra-traits"] -[workspace.dependencies.chirp-workflow] -path = "packages/common/chirp-workflow/core" +[workspace.dependencies.url] +version = "2.5.4" +features = ["serde"] -[workspace.dependencies.chirp-workflow-macros] -path = "packages/common/chirp-workflow/macros" +[workspace.dependencies.uuid] +version = "1.11.0" +features = ["v4","serde"] -[workspace.dependencies.chirp-client] -path = "packages/common/chirp/client" +[workspace.dependencies.tokio] +version = "1.44.0" +features = ["full","tracing"] -[workspace.dependencies.chirp-metrics] -path = "packages/common/chirp/metrics" +[workspace.dependencies.tokio-postgres] +version = "0.7" +features = ["with-chrono-0_4"] -[workspace.dependencies.chirp-perf] -path = "packages/common/chirp/perf" +[workspace.dependencies.deadpool-postgres] +version = "0.14.1" -[workspace.dependencies.chirp-types] -path = "packages/common/chirp/types" +[workspace.dependencies.tracing-logfmt] +version = "0.3" +features = ["ansi_logs"] + +[workspace.dependencies.tracing-subscriber] +version = "0.3" +default-features = false +features = ["ansi","fmt","json","env-filter"] -[workspace.dependencies.chirp-worker] -path = "packages/common/chirp/worker" +[workspace.dependencies.rivet-api-builder] +path = "packages/common/api-builder" -[workspace.dependencies.chirp-worker-attributes] -path = "packages/common/chirp/worker-attributes" +[workspace.dependencies.rivet-api-client] +path = "packages/common/api-client" -[workspace.dependencies.rivet-claims] -path = "packages/common/claims" +[workspace.dependencies.rivet-api-types] +path = "packages/common/api-types" + +[workspace.dependencies.rivet-api-util] +path = "packages/common/api-util" + +[workspace.dependencies.rivet-cache] +path = "packages/common/cache/build" + +[workspace.dependencies.rivet-cache-result] +path = "packages/common/cache/result" [workspace.dependencies.clickhouse-inserter] path = "packages/common/clickhouse-inserter" @@ -132,32 +269,24 @@ path = "packages/common/clickhouse-user-query" [workspace.dependencies.rivet-config] path = "packages/common/config" -[workspace.dependencies.rivet-connection] -path = "packages/common/connection" - -[workspace.dependencies.rivet-convert] -path = "packages/common/convert" - -[workspace.dependencies.deno-embed] -path = "packages/common/deno-embed" - [workspace.dependencies.rivet-env] path = "packages/common/env" -[workspace.dependencies.fdb-util] -path = "packages/common/fdb-util" +[workspace.dependencies.rivet-error] +path = "packages/common/error/core" -[workspace.dependencies.formatted-error] -path = "packages/common/formatted-error" +[workspace.dependencies.rivet-error-macros] +path = "packages/common/error/macros" -[workspace.dependencies.global-error] -path = "packages/common/global-error" +[workspace.dependencies.gas] +package = "gasoline" +path = "packages/common/gasoline/core" -[workspace.dependencies.rivet-health-checks] -path = "packages/common/health-checks" +[workspace.dependencies.gasoline] +path = "packages/common/gasoline/core" -[workspace.dependencies.kv-str] -path = "packages/common/kv-str" +[workspace.dependencies.gasoline-macros] +path = "packages/common/gasoline/macros" [workspace.dependencies.rivet-logs] path = "packages/common/logs" @@ -165,125 +294,32 @@ path = "packages/common/logs" [workspace.dependencies.rivet-metrics] path = "packages/common/metrics" -[workspace.dependencies.rivet-migrate] -path = "packages/common/migrate" - -[workspace.dependencies.nomad-util] -path = "packages/common/nomad-util" - -[workspace.dependencies.rivet-operation] -path = "packages/common/operation/core" - -[workspace.dependencies.rivet-operation-macros] -path = "packages/common/operation/macros" - [workspace.dependencies.rivet-pools] path = "packages/common/pools" -[workspace.dependencies.redis-util] -path = "packages/common/redis-util" - [workspace.dependencies.rivet-runtime] path = "packages/common/runtime" -[workspace.dependencies.s3-util] -path = "packages/common/s3-util" - -[workspace.dependencies.schemac] -path = "packages/common/schemac" - -[workspace.dependencies.rivet-server-cli] -path = "packages/common/server-cli" - -[workspace.dependencies.service-discovery] -path = "packages/common/service-discovery" - [workspace.dependencies.rivet-service-manager] path = "packages/common/service-manager" -[workspace.dependencies.rivet-auth] -path = "packages/common/smithy-output/api-auth/rust" - -[workspace.dependencies.rivet-auth-server] -path = "packages/common/smithy-output/api-auth/rust-server" - -[workspace.dependencies.rivet-cf-verification] -path = "packages/common/smithy-output/api-cf-verification/rust" - -[workspace.dependencies.rivet-cf-verification-server] -path = "packages/common/smithy-output/api-cf-verification/rust-server" - -[workspace.dependencies.rivet-cloud] -path = "packages/common/smithy-output/api-cloud/rust" - -[workspace.dependencies.rivet-cloud-server] -path = "packages/common/smithy-output/api-cloud/rust-server" - -[workspace.dependencies.rivet-group] -path = "packages/common/smithy-output/api-group/rust" - -[workspace.dependencies.rivet-group-server] -path = "packages/common/smithy-output/api-group/rust-server" - -[workspace.dependencies.rivet-identity] -path = "packages/common/smithy-output/api-identity/rust" - -[workspace.dependencies.rivet-identity-server] -path = "packages/common/smithy-output/api-identity/rust-server" - -[workspace.dependencies.rivet-job] -path = "packages/common/smithy-output/api-job/rust" - -[workspace.dependencies.rivet-job-server] -path = "packages/common/smithy-output/api-job/rust-server" - -[workspace.dependencies.rivet-kv] -path = "packages/common/smithy-output/api-kv/rust" - -[workspace.dependencies.rivet-kv-server] -path = "packages/common/smithy-output/api-kv/rust-server" - -[workspace.dependencies.rivet-matchmaker] -path = "packages/common/smithy-output/api-matchmaker/rust" - -[workspace.dependencies.rivet-matchmaker-server] -path = "packages/common/smithy-output/api-matchmaker/rust-server" - -[workspace.dependencies.rivet-party] -path = "packages/common/smithy-output/api-party/rust" - -[workspace.dependencies.rivet-party-server] -path = "packages/common/smithy-output/api-party/rust-server" - -[workspace.dependencies.rivet-portal] -path = "packages/common/smithy-output/api-portal/rust" - -[workspace.dependencies.rivet-portal-server] -path = "packages/common/smithy-output/api-portal/rust-server" +[workspace.dependencies.rivet-test-deps] +path = "packages/common/test-deps" -[workspace.dependencies.rivet-status] -path = "packages/common/smithy-output/api-status/rust" +[workspace.dependencies.rivet-test-deps-docker] +path = "packages/common/test-deps-docker" -[workspace.dependencies.rivet-status-server] -path = "packages/common/smithy-output/api-status/rust-server" +[workspace.dependencies.rivet-types] +path = "packages/common/types" -[workspace.dependencies.rivet-route] -path = "packages/common/smithy-output/api-traefik-provider/rust" +[workspace.dependencies.udb-util] +path = "packages/common/udb-util" -[workspace.dependencies.rivet-traefik-provider-server] -path = "packages/common/smithy-output/api-traefik-provider/rust-server" +[workspace.dependencies.universaldb] +path = "packages/common/universaldb" -[workspace.dependencies.rivet-test] -path = "packages/common/test" - -[workspace.dependencies.rivet-test-images] -path = "packages/common/test-images" - -[workspace.dependencies.types-proto-build] -path = "packages/common/types-proto/build" - -[workspace.dependencies.types-proto] -path = "packages/common/types-proto/core" +[workspace.dependencies.universalpubsub] +path = "packages/common/universalpubsub" [workspace.dependencies.rivet-util] path = "packages/common/util/core" @@ -292,744 +328,77 @@ path = "packages/common/util/core" package = "rivet-util" path = "packages/common/util/core" -[workspace.dependencies.rivet-util-macros] -path = "packages/common/util/macros" - -[workspace.dependencies.rivet-util-search] -path = "packages/common/util/search" - -[workspace.dependencies.util-search] -package = "rivet-util-search" -path = "packages/common/util/search" - -[workspace.dependencies.api-core-actor] -path = "packages/core/api/actor" - -[workspace.dependencies.api-auth] -path = "packages/core/api/auth" - -[workspace.dependencies.api-cf-verification] -path = "packages/core/api/cf-verification" - -[workspace.dependencies.api-cloud] -path = "packages/core/api/cloud" - -[workspace.dependencies.api-games] -path = "packages/core/api/games" - -[workspace.dependencies.api-group] -path = "packages/core/api/group" - -[workspace.dependencies.api-identity] -path = "packages/core/api/identity" - -[workspace.dependencies.api-core-intercom] -path = "packages/core/api/intercom" - -[workspace.dependencies.api-job] -path = "packages/core/api/job" - -[workspace.dependencies.api-matchmaker] -path = "packages/core/api/matchmaker" - -[workspace.dependencies.api-core-monolith-edge] -path = "packages/core/api/monolith-edge" - -[workspace.dependencies.api-core-monolith-public] -path = "packages/core/api/monolith-public" - -[workspace.dependencies.api-portal] -path = "packages/core/api/portal" - -[workspace.dependencies.api-provision] -path = "packages/core/api/provision" - -[workspace.dependencies.api-status] -path = "packages/core/api/status" - -[workspace.dependencies.api-core-traefik-provider] -path = "packages/core/api/traefik-provider" - -[workspace.dependencies.api-ui] -path = "packages/core/api/ui" - -[workspace.dependencies.rivet-job-runner] -path = "packages/core/infra/legacy/job-runner" - -[workspace.dependencies.rivet-schema-generator] -path = "packages/core/infra/schema-generator" - -[workspace.dependencies.rivet-server] -path = "packages/core/infra/server" - -[workspace.dependencies.build] -path = "packages/core/services/build" - -[workspace.dependencies.build-create] -path = "packages/core/services/build/ops/create" - -[workspace.dependencies.build-get] -path = "packages/core/services/build/ops/get" - -[workspace.dependencies.build-list-for-env] -path = "packages/core/services/build/ops/list-for-env" - -[workspace.dependencies.build-list-for-game] -path = "packages/core/services/build/ops/list-for-game" - -[workspace.dependencies.build-default-create] -path = "packages/core/services/build/standalone/default-create" - -[workspace.dependencies.rivet-util-build] -path = "packages/core/services/build/util" - -[workspace.dependencies.util-build] -package = "rivet-util-build" -path = "packages/core/services/build/util" - -[workspace.dependencies.captcha-hcaptcha-config-get] -path = "packages/core/services/captcha/ops/hcaptcha-config-get" - -[workspace.dependencies.captcha-hcaptcha-verify] -path = "packages/core/services/captcha/ops/hcaptcha-verify" - -[workspace.dependencies.captcha-request] -path = "packages/core/services/captcha/ops/request" - -[workspace.dependencies.captcha-turnstile-config-get] -path = "packages/core/services/captcha/ops/turnstile-config-get" - -[workspace.dependencies.captcha-turnstile-verify] -path = "packages/core/services/captcha/ops/turnstile-verify" - -[workspace.dependencies.captcha-verify] -path = "packages/core/services/captcha/ops/verify" - -[workspace.dependencies.rivet-util-captcha] -path = "packages/core/services/captcha/util" - -[workspace.dependencies.util-captcha] -package = "rivet-util-captcha" -path = "packages/core/services/captcha/util" - -[workspace.dependencies.cdn-namespace-auth-user-remove] -path = "packages/core/services/cdn/ops/namespace-auth-user-remove" - -[workspace.dependencies.cdn-namespace-auth-user-update] -path = "packages/core/services/cdn/ops/namespace-auth-user-update" - -[workspace.dependencies.cdn-namespace-create] -path = "packages/core/services/cdn/ops/namespace-create" - -[workspace.dependencies.cdn-namespace-domain-create] -path = "packages/core/services/cdn/ops/namespace-domain-create" - -[workspace.dependencies.cdn-namespace-domain-remove] -path = "packages/core/services/cdn/ops/namespace-domain-remove" - -[workspace.dependencies.cdn-namespace-get] -path = "packages/core/services/cdn/ops/namespace-get" - -[workspace.dependencies.cdn-namespace-resolve-domain] -path = "packages/core/services/cdn/ops/namespace-resolve-domain" - -[workspace.dependencies.cdn-ns-auth-type-set] -path = "packages/core/services/cdn/ops/ns-auth-type-set" - -[workspace.dependencies.cdn-ns-enable-domain-public-auth-set] -path = "packages/core/services/cdn/ops/ns-enable-domain-public-auth-set" - -[workspace.dependencies.cdn-site-create] -path = "packages/core/services/cdn/ops/site-create" - -[workspace.dependencies.cdn-site-get] -path = "packages/core/services/cdn/ops/site-get" - -[workspace.dependencies.cdn-site-list-for-game] -path = "packages/core/services/cdn/ops/site-list-for-game" - -[workspace.dependencies.cdn-version-get] -path = "packages/core/services/cdn/ops/version-get" - -[workspace.dependencies.cdn-version-prepare] -path = "packages/core/services/cdn/ops/version-prepare" - -[workspace.dependencies.cdn-version-publish] -path = "packages/core/services/cdn/ops/version-publish" - -[workspace.dependencies.rivet-util-cdn] -path = "packages/core/services/cdn/util" - -[workspace.dependencies.util-cdn] -package = "rivet-util-cdn" -path = "packages/core/services/cdn/util" - -[workspace.dependencies.cdn-worker] -path = "packages/core/services/cdn/worker" - -[workspace.dependencies.cf-custom-hostname-get] -path = "packages/core/services/cf-custom-hostname/ops/get" - -[workspace.dependencies.cf-custom-hostname-list-for-namespace-id] -path = "packages/core/services/cf-custom-hostname/ops/list-for-namespace-id" - -[workspace.dependencies.cf-custom-hostname-resolve-hostname] -path = "packages/core/services/cf-custom-hostname/ops/resolve-hostname" - -[workspace.dependencies.cf-custom-hostname-worker] -path = "packages/core/services/cf-custom-hostname/worker" - -[workspace.dependencies.cloud-device-link-create] -path = "packages/core/services/cloud/ops/device-link-create" - -[workspace.dependencies.cloud-game-config-create] -path = "packages/core/services/cloud/ops/game-config-create" - -[workspace.dependencies.cloud-game-config-get] -path = "packages/core/services/cloud/ops/game-config-get" - -[workspace.dependencies.cloud-game-token-create] -path = "packages/core/services/cloud/ops/game-token-create" - -[workspace.dependencies.cloud-namespace-create] -path = "packages/core/services/cloud/ops/namespace-create" - -[workspace.dependencies.cloud-namespace-get] -path = "packages/core/services/cloud/ops/namespace-get" - -[workspace.dependencies.cloud-namespace-token-development-create] -path = "packages/core/services/cloud/ops/namespace-token-development-create" - -[workspace.dependencies.cloud-namespace-token-public-create] -path = "packages/core/services/cloud/ops/namespace-token-public-create" - -[workspace.dependencies.cloud-version-get] -path = "packages/core/services/cloud/ops/version-get" - -[workspace.dependencies.cloud-version-publish] -path = "packages/core/services/cloud/ops/version-publish" - -[workspace.dependencies.cloud-default-create] -path = "packages/core/services/cloud/standalone/default-create" - -[workspace.dependencies.cloud-worker] -path = "packages/core/services/cloud/worker" - -[workspace.dependencies.cluster] -path = "packages/core/services/cluster" - -[workspace.dependencies.cluster-datacenter-tls-renew] -path = "packages/core/services/cluster/standalone/datacenter-tls-renew" +[workspace.dependencies.rivet-util-id] +path = "packages/common/util/id" -[workspace.dependencies.cluster-default-update] -path = "packages/core/services/cluster/standalone/default-update" +[workspace.dependencies.versioned-data-util] +path = "packages/common/versioned-data-util" -[workspace.dependencies.cluster-gc] -path = "packages/core/services/cluster/standalone/gc" - -[workspace.dependencies.cluster-metrics-publish] -path = "packages/core/services/cluster/standalone/metrics-publish" - -[workspace.dependencies.custom-user-avatar-list-for-game] -path = "packages/core/services/custom-user-avatar/ops/list-for-game" - -[workspace.dependencies.custom-user-avatar-upload-complete] -path = "packages/core/services/custom-user-avatar/ops/upload-complete" - -[workspace.dependencies.debug-email-res] -path = "packages/core/services/debug/ops/email-res" - -[workspace.dependencies.dynamic-config] -path = "packages/core/services/dynamic-config" - -[workspace.dependencies.email-verification-complete] -path = "packages/core/services/email-verification/ops/complete" - -[workspace.dependencies.email-verification-create] -path = "packages/core/services/email-verification/ops/create" - -[workspace.dependencies.email-send] -path = "packages/core/services/email/ops/send" - -[workspace.dependencies.external-request-validate] -path = "packages/core/services/external/ops/request-validate" - -[workspace.dependencies.external-worker] -path = "packages/core/services/external/worker" - -[workspace.dependencies.faker-build] -path = "packages/core/services/faker/ops/build" - -[workspace.dependencies.faker-cdn-site] -path = "packages/core/services/faker/ops/cdn-site" - -[workspace.dependencies.faker-game] -path = "packages/core/services/faker/ops/game" - -[workspace.dependencies.faker-game-namespace] -path = "packages/core/services/faker/ops/game-namespace" - -[workspace.dependencies.faker-game-version] -path = "packages/core/services/faker/ops/game-version" - -[workspace.dependencies.faker-job-run] -path = "packages/core/services/faker/ops/job-run" - -[workspace.dependencies.faker-job-template] -path = "packages/core/services/faker/ops/job-template" - -[workspace.dependencies.faker-mm-lobby] -path = "packages/core/services/faker/ops/mm-lobby" - -[workspace.dependencies.faker-mm-lobby-row] -path = "packages/core/services/faker/ops/mm-lobby-row" - -[workspace.dependencies.faker-mm-player] -path = "packages/core/services/faker/ops/mm-player" - -[workspace.dependencies.faker-region] -path = "packages/core/services/faker/ops/region" - -[workspace.dependencies.faker-team] -path = "packages/core/services/faker/ops/team" - -[workspace.dependencies.faker-user] -path = "packages/core/services/faker/ops/user" - -[workspace.dependencies.game-banner-upload-complete] -path = "packages/core/services/game/ops/banner-upload-complete" - -[workspace.dependencies.game-create] -path = "packages/core/services/game/ops/create" - -[workspace.dependencies.game-get] -path = "packages/core/services/game/ops/get" - -[workspace.dependencies.game-list-all] -path = "packages/core/services/game/ops/list-all" - -[workspace.dependencies.game-list-for-team] -path = "packages/core/services/game/ops/list-for-team" - -[workspace.dependencies.game-logo-upload-complete] -path = "packages/core/services/game/ops/logo-upload-complete" - -[workspace.dependencies.game-namespace-create] -path = "packages/core/services/game/ops/namespace-create" - -[workspace.dependencies.game-namespace-get] -path = "packages/core/services/game/ops/namespace-get" - -[workspace.dependencies.game-namespace-list] -path = "packages/core/services/game/ops/namespace-list" - -[workspace.dependencies.game-namespace-resolve-name-id] -path = "packages/core/services/game/ops/namespace-resolve-name-id" - -[workspace.dependencies.game-namespace-resolve-url] -path = "packages/core/services/game/ops/namespace-resolve-url" - -[workspace.dependencies.game-namespace-validate] -path = "packages/core/services/game/ops/namespace-validate" - -[workspace.dependencies.game-namespace-version-history-list] -path = "packages/core/services/game/ops/namespace-version-history-list" - -[workspace.dependencies.game-namespace-version-set] -path = "packages/core/services/game/ops/namespace-version-set" - -[workspace.dependencies.game-recommend] -path = "packages/core/services/game/ops/recommend" - -[workspace.dependencies.game-resolve-name-id] -path = "packages/core/services/game/ops/resolve-name-id" - -[workspace.dependencies.game-resolve-namespace-id] -path = "packages/core/services/game/ops/resolve-namespace-id" - -[workspace.dependencies.game-token-development-validate] -path = "packages/core/services/game/ops/token-development-validate" - -[workspace.dependencies.game-validate] -path = "packages/core/services/game/ops/validate" - -[workspace.dependencies.game-version-create] -path = "packages/core/services/game/ops/version-create" - -[workspace.dependencies.game-version-get] -path = "packages/core/services/game/ops/version-get" - -[workspace.dependencies.game-version-list] -path = "packages/core/services/game/ops/version-list" - -[workspace.dependencies.game-version-validate] -path = "packages/core/services/game/ops/version-validate" - -[workspace.dependencies.ip-info] -path = "packages/core/services/ip/ops/info" - -[workspace.dependencies.job-log-read] -path = "packages/core/services/job-log/ops/read" - -[workspace.dependencies.job-log-worker] -path = "packages/core/services/job-log/worker" - -[workspace.dependencies.job-run] -path = "packages/core/services/job-run" - -[workspace.dependencies.job-gc] -path = "packages/core/services/job/standalone/gc" - -[workspace.dependencies.rivet-util-job] -path = "packages/core/services/job/util" - -[workspace.dependencies.util-job] -package = "rivet-util-job" -path = "packages/core/services/job/util" - -[workspace.dependencies.linode] -path = "packages/core/services/linode" - -[workspace.dependencies.linode-gc] -path = "packages/core/services/linode/standalone/gc" - -[workspace.dependencies.load-test-api-cloud] -path = "packages/core/services/load-test/standalone/api-cloud" - -[workspace.dependencies.load-test-mm] -path = "packages/core/services/load-test/standalone/mm" - -[workspace.dependencies.load-test-mm-sustain] -path = "packages/core/services/load-test/standalone/mm-sustain" - -[workspace.dependencies.load-test-sqlx] -path = "packages/core/services/load-test/standalone/sqlx" - -[workspace.dependencies.load-test-watch-requests] -path = "packages/core/services/load-test/standalone/watch-requests" - -[workspace.dependencies.mm-config-game-get] -path = "packages/core/services/mm-config/ops/game-get" - -[workspace.dependencies.mm-config-game-upsert] -path = "packages/core/services/mm-config/ops/game-upsert" - -[workspace.dependencies.mm-config-lobby-group-get] -path = "packages/core/services/mm-config/ops/lobby-group-get" - -[workspace.dependencies.mm-config-lobby-group-resolve-name-id] -path = "packages/core/services/mm-config/ops/lobby-group-resolve-name-id" - -[workspace.dependencies.mm-config-lobby-group-resolve-version] -path = "packages/core/services/mm-config/ops/lobby-group-resolve-version" - -[workspace.dependencies.mm-config-namespace-config-set] -path = "packages/core/services/mm-config/ops/namespace-config-set" - -[workspace.dependencies.mm-config-namespace-config-validate] -path = "packages/core/services/mm-config/ops/namespace-config-validate" - -[workspace.dependencies.mm-config-namespace-create] -path = "packages/core/services/mm-config/ops/namespace-create" - -[workspace.dependencies.mm-config-namespace-get] -path = "packages/core/services/mm-config/ops/namespace-get" - -[workspace.dependencies.mm-config-version-get] -path = "packages/core/services/mm-config/ops/version-get" - -[workspace.dependencies.mm-config-version-prepare] -path = "packages/core/services/mm-config/ops/version-prepare" - -[workspace.dependencies.mm-config-version-publish] -path = "packages/core/services/mm-config/ops/version-publish" - -[workspace.dependencies.mm-dev-player-token-create] -path = "packages/core/services/mm/ops/dev-player-token-create" - -[workspace.dependencies.mm-lobby-find-fail] -path = "packages/core/services/mm/ops/lobby-find-fail" - -[workspace.dependencies.mm-lobby-find-lobby-query-list] -path = "packages/core/services/mm/ops/lobby-find-lobby-query-list" - -[workspace.dependencies.mm-lobby-find-try-complete] -path = "packages/core/services/mm/ops/lobby-find-try-complete" - -[workspace.dependencies.mm-lobby-for-run-id] -path = "packages/core/services/mm/ops/lobby-for-run-id" - -[workspace.dependencies.mm-lobby-get] -path = "packages/core/services/mm/ops/lobby-get" - -[workspace.dependencies.mm-lobby-history] -path = "packages/core/services/mm/ops/lobby-history" - -[workspace.dependencies.mm-lobby-idle-update] -path = "packages/core/services/mm/ops/lobby-idle-update" - -[workspace.dependencies.mm-lobby-list-for-namespace] -path = "packages/core/services/mm/ops/lobby-list-for-namespace" - -[workspace.dependencies.mm-lobby-list-for-user-id] -path = "packages/core/services/mm/ops/lobby-list-for-user-id" - -[workspace.dependencies.mm-lobby-player-count] -path = "packages/core/services/mm/ops/lobby-player-count" - -[workspace.dependencies.mm-lobby-runtime-aggregate] -path = "packages/core/services/mm/ops/lobby-runtime-aggregate" - -[workspace.dependencies.mm-lobby-state-get] -path = "packages/core/services/mm/ops/lobby-state-get" - -[workspace.dependencies.mm-player-count-for-namespace] -path = "packages/core/services/mm/ops/player-count-for-namespace" - -[workspace.dependencies.mm-player-get] -path = "packages/core/services/mm/ops/player-get" - -[workspace.dependencies.mm-gc] -path = "packages/core/services/mm/standalone/gc" - -[workspace.dependencies.rivet-util-mm] -path = "packages/core/services/mm/util" - -[workspace.dependencies.util-mm] -package = "rivet-util-mm" -path = "packages/core/services/mm/util" - -[workspace.dependencies.mm-worker] -path = "packages/core/services/mm/worker" - -[workspace.dependencies.monolith-worker] -path = "packages/core/services/monolith/standalone/worker" - -[workspace.dependencies.monolith-workflow-worker] -path = "packages/core/services/monolith/standalone/workflow-worker" - -[workspace.dependencies.nomad-monitor] -path = "packages/core/services/nomad/standalone/monitor" - -[workspace.dependencies.region-get] -path = "packages/core/services/region/ops/get" - -[workspace.dependencies.region-list] -path = "packages/core/services/region/ops/list" - -[workspace.dependencies.region-list-for-game] -path = "packages/core/services/region/ops/list-for-game" - -[workspace.dependencies.region-recommend] -path = "packages/core/services/region/ops/recommend" - -[workspace.dependencies.region-resolve] -path = "packages/core/services/region/ops/resolve" - -[workspace.dependencies.region-resolve-for-game] -path = "packages/core/services/region/ops/resolve-for-game" - -[workspace.dependencies.route] -path = "packages/core/services/route" - -[workspace.dependencies.server-spec] -path = "packages/core/services/server-spec" - -[workspace.dependencies.team-invite-get] -path = "packages/core/services/team-invite/ops/get" - -[workspace.dependencies.team-invite-worker] -path = "packages/core/services/team-invite/worker" - -[workspace.dependencies.team-avatar-upload-complete] -path = "packages/core/services/team/ops/avatar-upload-complete" - -[workspace.dependencies.team-get] -path = "packages/core/services/team/ops/get" - -[workspace.dependencies.team-join-request-list] -path = "packages/core/services/team/ops/join-request-list" - -[workspace.dependencies.team-member-count] -path = "packages/core/services/team/ops/member-count" - -[workspace.dependencies.team-member-get] -path = "packages/core/services/team/ops/member-get" - -[workspace.dependencies.team-member-list] -path = "packages/core/services/team/ops/member-list" - -[workspace.dependencies.team-member-relationship-get] -path = "packages/core/services/team/ops/member-relationship-get" - -[workspace.dependencies.team-profile-validate] -path = "packages/core/services/team/ops/profile-validate" - -[workspace.dependencies.team-recommend] -path = "packages/core/services/team/ops/recommend" - -[workspace.dependencies.team-resolve-display-name] -path = "packages/core/services/team/ops/resolve-display-name" - -[workspace.dependencies.team-user-ban-get] -path = "packages/core/services/team/ops/user-ban-get" - -[workspace.dependencies.team-user-ban-list] -path = "packages/core/services/team/ops/user-ban-list" - -[workspace.dependencies.team-validate] -path = "packages/core/services/team/ops/validate" - -[workspace.dependencies.rivet-util-team] -path = "packages/core/services/team/util" - -[workspace.dependencies.util-team] -package = "rivet-util-team" -path = "packages/core/services/team/util" - -[workspace.dependencies.team-worker] -path = "packages/core/services/team/worker" - -[workspace.dependencies.telemetry-beacon] -path = "packages/core/services/telemetry/standalone/beacon" - -[workspace.dependencies.tier] -path = "packages/core/services/tier" - -[workspace.dependencies.token-create] -path = "packages/core/services/token/ops/create" - -[workspace.dependencies.token-exchange] -path = "packages/core/services/token/ops/exchange" - -[workspace.dependencies.token-get] -path = "packages/core/services/token/ops/get" - -[workspace.dependencies.token-revoke] -path = "packages/core/services/token/ops/revoke" - -[workspace.dependencies.upload-complete] -path = "packages/core/services/upload/ops/complete" - -[workspace.dependencies.upload-file-list] -path = "packages/core/services/upload/ops/file-list" - -[workspace.dependencies.upload-get] -path = "packages/core/services/upload/ops/get" - -[workspace.dependencies.upload-list-for-user] -path = "packages/core/services/upload/ops/list-for-user" - -[workspace.dependencies.upload-prepare] -path = "packages/core/services/upload/ops/prepare" - -[workspace.dependencies.upload-worker] -path = "packages/core/services/upload/worker" - -[workspace.dependencies.user] -path = "packages/core/services/user" - -[workspace.dependencies.user-identity-create] -path = "packages/core/services/user-identity/ops/create" - -[workspace.dependencies.user-identity-delete] -path = "packages/core/services/user-identity/ops/delete" - -[workspace.dependencies.user-identity-get] -path = "packages/core/services/user-identity/ops/get" - -[workspace.dependencies.user-avatar-upload-complete] -path = "packages/core/services/user/ops/avatar-upload-complete" - -[workspace.dependencies.user-get] -path = "packages/core/services/user/ops/get" - -[workspace.dependencies.user-pending-delete-toggle] -path = "packages/core/services/user/ops/pending-delete-toggle" - -[workspace.dependencies.user-profile-validate] -path = "packages/core/services/user/ops/profile-validate" - -[workspace.dependencies.user-resolve-email] -path = "packages/core/services/user/ops/resolve-email" - -[workspace.dependencies.user-team-list] -path = "packages/core/services/user/ops/team-list" - -[workspace.dependencies.user-token-create] -path = "packages/core/services/user/ops/token-create" - -[workspace.dependencies.user-delete-pending] -path = "packages/core/services/user/standalone/delete-pending" - -[workspace.dependencies.user-worker] -path = "packages/core/services/user/worker" - -[workspace.dependencies.api-edge-actor] -path = "packages/edge/api/actor" +[workspace.dependencies.pegboard-actor-kv] +path = "packages/core/actor-kv" -[workspace.dependencies.api-edge-intercom] -path = "packages/edge/api/intercom" +[workspace.dependencies.rivet-api-peer] +path = "packages/core/api-peer" -[workspace.dependencies.api-edge-monolith-edge] -path = "packages/edge/api/monolith-edge" +[workspace.dependencies.rivet-api-public] +path = "packages/core/api-public" -[workspace.dependencies.api-edge-monolith-public] -path = "packages/edge/api/monolith-public" +[workspace.dependencies.rivet-bootstrap] +path = "packages/core/bootstrap" -[workspace.dependencies.api-edge-traefik-provider] -path = "packages/edge/api/traefik-provider" +[workspace.dependencies.rivet-dump-openapi] +path = "packages/core/dump-openapi" -[workspace.dependencies.pegboard-actor-kv] -path = "packages/edge/infra/client/actor-kv" - -[workspace.dependencies.pegboard-config] -path = "packages/edge/infra/client/config" +[workspace.dependencies.rivet-guard-core] +path = "packages/core/guard/core" -[workspace.dependencies.pegboard-container-runner] -path = "packages/edge/infra/client/container-runner" +[workspace.dependencies.rivet-guard] +path = "packages/core/guard/server" -[workspace.dependencies.pegboard-echo-server] -path = "packages/edge/infra/client/echo" +[workspace.dependencies.pegboard-gateway] +path = "packages/core/pegboard-gateway" -[workspace.dependencies.pegboard-isolate-v8-runner] -path = "packages/edge/infra/client/isolate-v8-runner" +[workspace.dependencies.pegboard-runner-ws] +path = "packages/core/pegboard-runner-ws" -[workspace.dependencies.pegboard-manager] -path = "packages/edge/infra/client/manager" +[workspace.dependencies.pegboard-tunnel] +path = "packages/core/pegboard-tunnel" -[workspace.dependencies.rivet-edge-server] -path = "packages/edge/infra/edge-server" +[workspace.dependencies.rivet-workflow-worker] +path = "packages/core/workflow-worker" -[workspace.dependencies.rivet-guard-core] -path = "packages/edge/infra/guard/core" +[workspace.dependencies.rivet-engine] +path = "packages/infra/engine" -[workspace.dependencies.rivet-guard] -path = "packages/edge/infra/guard/server" +[workspace.dependencies.epoxy] +path = "packages/services/epoxy" -[workspace.dependencies.edge-monolith-workflow-worker] -path = "packages/edge/services/monolith/standalone/workflow-worker" +[workspace.dependencies.namespace] +path = "packages/services/namespace" [workspace.dependencies.pegboard] -path = "packages/edge/services/pegboard" +path = "packages/services/pegboard" + +[workspace.dependencies.rivet-api-full] +path = "sdks/rust/api-full" -[workspace.dependencies.pegboard-usage-metrics-publish] -path = "packages/edge/services/pegboard/standalone/usage-metrics-publish" +[workspace.dependencies.rivet-api-runtime] +path = "sdks/rust/api-runtime" -[workspace.dependencies.pegboard-ws] -path = "packages/edge/services/pegboard/standalone/ws" +[workspace.dependencies.bare_gen] +path = "sdks/rust/bare_gen" -[workspace.dependencies.rivet-cli] -path = "packages/toolchain/cli" +[workspace.dependencies.epoxy-protocol] +path = "sdks/rust/epoxy-protocol" -[workspace.dependencies.rivet-js-utils-embed] -path = "packages/toolchain/js-utils-embed" +[workspace.dependencies.rivet-key-data] +path = "sdks/rust/key-data" -[workspace.dependencies.rivet-toolchain] -path = "packages/toolchain/toolchain" +[workspace.dependencies.rivet-runner-protocol] +path = "sdks/rust/runner-protocol" -[workspace.dependencies.rivet-api] -path = "sdks/api/full/rust" +[workspace.dependencies.rivet-tunnel-protocol] +path = "sdks/rust/tunnel-protocol" [profile.dev] overflow-checks = false diff --git a/biome.json b/biome.json index a47555e0be..f5477ba2ae 100644 --- a/biome.json +++ b/biome.json @@ -1,84 +1,32 @@ { - "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", - "files": { - "ignore": [ - "**/node_modules/**", - "**/dist/**", - "**/build/**", - "**/coverage/**", - "**/tmp", - "**/.turbo/**", - "**/generated/**", - "*.gen.*", - "**/.next/**", - ".vscode/**", - "docker/**", - "docs/**", - "docs-internal/**", - "externals/**", - "modules/**", - "scripts/**", - "namespaces/**", - "secrets/**", - "sdks/api/**", - "*.lock", - "resources/**", - "site/framer/**", - "**/out/**", - "packages/edge/infra/**", - "packages/common/**", - "packages/api/**", - "packages/services/**", - "packages/toolchain/**" - ], - "ignoreUnknown": true - }, - "vcs": { - "enabled": true, - "clientKind": "git", - "useIgnoreFile": true, - "defaultBranch": "main" - }, - "formatter": { - "enabled": true, - "useEditorconfig": true - }, - "organizeImports": { "enabled": true }, - "linter": { - "enabled": true, - "rules": { - "recommended": true, - "correctness": { - "noUnusedImports": "warn" - } - } - }, - "overrides": [ - { - "include": ["site/**/*.css"], - "linter": { - "rules": { - "correctness": { - "noInvalidPositionAtImportRule": "off", - "noUnknownFunction": "off" - } - } - } - }, - { - "include": ["site/**/*.js*"], - "linter": { - "enabled": false - } - }, - { - "include": [ - "sdks/actor/bridge/**/lib/**/*", - "sdks/**/bridge_types/**/lib/**/*" - ], - "linter": { - "enabled": false - } - } - ] + "$schema": "https://biomejs.dev/schemas/2.1.1/schema.json", + "files": { + "includes": ["**/*.json", "**/*.ts", "**/*.tsx", "**/*.js", "!examples/snippets/**"], + "ignoreUnknown": true + }, + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true, + "defaultBranch": "main" + }, + "formatter": { + "enabled": true, + "useEditorconfig": true + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "style": { + "noUselessElse": "off" + }, + "correctness": { + "noUnusedImports": "warn" + }, + "suspicious": { + "noExplicitAny": "off" + } + } + } } diff --git a/cloud/packages/ci-manager/Dockerfile b/cloud/packages/ci-manager/Dockerfile deleted file mode 100644 index 631e6830ab..0000000000 --- a/cloud/packages/ci-manager/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -# Build stage - includes dev dependencies -FROM node:22-alpine AS builder -ENV NODE_ENV=development - -WORKDIR /app -RUN npm i -g corepack && corepack enable -COPY package.json yarn.lock ./ -RUN yarn install --immutable -COPY . . -RUN yarn build - -# Production stage - only prod dependencies -FROM node:22-alpine AS release -ENV NODE_ENV=production - -RUN adduser -s /bin/sh -D rivet -WORKDIR /app -RUN apk add --no-cache skopeo umoci && npm i -g corepack && corepack enable -COPY package.json yarn.lock ./ -RUN yarn config set nodeLinker node-modules && yarn install --immutable -COPY --from=builder /app/dist ./dist -RUN chown -R rivet:rivet /app -USER rivet -EXPOSE 3000 -CMD ["node", "dist/index.js"] diff --git a/cloud/packages/ci-manager/package.json b/cloud/packages/ci-manager/package.json deleted file mode 100644 index 22780507ec..0000000000 --- a/cloud/packages/ci-manager/package.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "ci-manager", - "private": true, - "peerDependencies": { - "typescript": "^5" - }, - "scripts": { - "prepare-builds": "tsx scripts/prepare-builds.ts", - "check-types": "tsc --noEmit", - "test": "vitest", - "build": "tsc" - }, - "dependencies": { - "@rivet-gg/api": "^25.4.2", - "hono": "^4.7.11", - "nanoevents": "^9.1.0", - "zod": "^3.25.56" - }, - "devDependencies": { - "@hono/node-server": "^1.14.4", - "@types/eventsource": "^1.1.15", - "@types/node": "^22.15.30", - "eventsource": "^4.0.0", - "get-port": "^7.1.0", - "tar": "^7.4.3", - "tsx": "^4.19.4", - "typescript": "^5.7.2", - "vitest": "^3.2.2", - "zx": "^8.1.9" - }, - "packageManager": "yarn@4.6.0" -} diff --git a/cloud/packages/ci-manager/src/build-store.ts b/cloud/packages/ci-manager/src/build-store.ts deleted file mode 100644 index d5715ef3bb..0000000000 --- a/cloud/packages/ci-manager/src/build-store.ts +++ /dev/null @@ -1,152 +0,0 @@ -import { randomUUID } from "crypto"; -import { dirname, join } from "path"; -import { mkdir, rm } from "fs/promises"; -import { createNanoEvents } from "nanoevents"; -import type { BuildEvent, BuildInfo, Status } from "./types"; - -export class BuildStore { - private builds = new Map(); - private tempDir: string; - public emitter = createNanoEvents<{ - "build-event": (buildId: string, event: BuildEvent) => void; - "status-change": (buildId: string, status: Status) => void; - }>(); - - constructor(tempDir = "/tmp/ci-builds") { - this.tempDir = tempDir; - } - - async init() { - await mkdir(this.tempDir, { recursive: true }); - } - - createBuild( - buildName: string, - dockerfilePath: string, - environmentId: string, - buildArgs: Record, - buildTarget: string | undefined, - ): string { - const id = randomUUID(); - const contextPath = join(this.tempDir, id, "context.tar.gz"); - const outputPath = join(this.tempDir, id, "output.tar.gz"); - - const build: BuildInfo = { - id, - status: { type: "starting", data: {} }, - buildName, - dockerfilePath, - environmentId, - contextPath, - buildArgs, - buildTarget, - outputPath, - events: [], - createdAt: new Date(), - }; - - // Set up 10-minute cleanup timeout - build.cleanupTimeout = setTimeout( - () => { - this.cleanupBuild(id, "timeout"); - }, - 10 * 60 * 1000, - ); // 10 minutes - - this.builds.set(id, build); - return id; - } - - getBuild(id: string): BuildInfo | undefined { - return this.builds.get(id); - } - - updateStatus(id: string, status: Status) { - const build = this.builds.get(id); - if ( - build && - build.status.type !== "success" && - build.status.type !== "failure" - ) { - build.status = status; - const event = { type: "status", data: status } as BuildEvent; - build.events.push(event); - this.emitter.emit("build-event", id, event); - this.emitter.emit("status-change", id, status); - console.log(`[${id}] status: ${JSON.stringify(status)}`); - } - } - - addLog(id: string, line: string) { - console.log(`[${id}] ${line}`); - const build = this.builds.get(id); - if (build) { - const event: BuildEvent = { type: "log", data: { line } }; - build.events.push(event); - this.emitter.emit("build-event", id, event); - } - } - - setContainerProcess(id: string, process: any) { - const build = this.builds.get(id); - if (build) { - build.containerProcess = process; - } - } - - getContextPath(id: string): string | undefined { - return this.builds.get(id)?.contextPath; - } - - getOutputPath(id: string): string | undefined { - return this.builds.get(id)?.outputPath; - } - - markDownloaded(id: string) { - const build = this.builds.get(id); - if (build) { - build.downloadedAt = new Date(); - // Trigger cleanup after download - setTimeout(() => { - this.cleanupBuild(id, "downloaded"); - }, 1000); // Small delay to ensure download is complete - } - } - - private async cleanupBuild(id: string, reason: "timeout" | "downloaded") { - const build = this.builds.get(id); - if (!build) return; - - console.log(`Cleaning up build ${id} (reason: ${reason})`); - - try { - // Clear the timeout if it exists - if (build.cleanupTimeout) { - clearTimeout(build.cleanupTimeout); - } - - // Remove build directory and all files - const buildDir = dirname(build.contextPath); - try { - await rm(buildDir, { recursive: true, force: true }); - console.log(`Removed build directory: ${buildDir}`); - } catch (error) { - console.warn( - `Failed to remove build directory ${buildDir}:`, - error, - ); - } - - // Remove from memory - this.builds.delete(id); - console.log(`Build ${id} cleaned up successfully`); - } catch (error) { - console.error(`Error cleaning up build ${id}:`, error); - } - } - - // Manual cleanup method for testing or admin use - async manualCleanup(id: string) { - await this.cleanupBuild(id, "downloaded"); - } -} diff --git a/cloud/packages/ci-manager/src/common.ts b/cloud/packages/ci-manager/src/common.ts deleted file mode 100644 index 56494820bc..0000000000 --- a/cloud/packages/ci-manager/src/common.ts +++ /dev/null @@ -1,42 +0,0 @@ -// Keep in sync with ci-runner/entry.sh -export const UNIT_SEP_CHAR = "\x1F"; -export const NO_SEP_CHAR_REGEX = /^[^\x1F]+$/; - -interface KanikoArguments { - contextUrl: string; - outputUrl: string; - destination: string; - dockerfilePath: string; - buildArgs: Record; - buildTarget?: string; -} - -// SAFETY: buildArgs keys never have equal signs or spaces -function convertBuildArgsToArgs(buildArgs: Record): string[] { - return Object.entries(buildArgs).flatMap(([key, value]) => [ - `--build-arg`, - `${key}=${value}`, - ]); -} - -export function serializeKanikoArguments(args: KanikoArguments): string { - // SAFETY: Nothing needed to be escaped, as values are already sanitized, - // and are joined by IFS=UNIT_SEP_CHAR (see entry.sh of ci-runner). - const preparedArgs = [ - ...convertBuildArgsToArgs(args.buildArgs), - `--context=${args.contextUrl}`, - `--destination=${args.destination}`, - `--upload-tar=${args.outputUrl}`, - `--dockerfile=${args.dockerfilePath}`, - ...(args.buildTarget ? [`--target='${args.buildTarget}'`] : []), - "--no-push", - "--single-snapshot", - "--verbosity=info", - ].map((arg) => { - // Args should never contain UNIT_SEP_CHAR, but we can - // escape it if they do. - return arg.replaceAll(UNIT_SEP_CHAR, "\\" + UNIT_SEP_CHAR); - }); - - return preparedArgs.join(UNIT_SEP_CHAR); -} diff --git a/cloud/packages/ci-manager/src/executors/docker.ts b/cloud/packages/ci-manager/src/executors/docker.ts deleted file mode 100644 index 11b37f800b..0000000000 --- a/cloud/packages/ci-manager/src/executors/docker.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { spawn } from "node:child_process"; -import type { BuildStore } from "../build-store"; -import { serializeKanikoArguments } from "../common"; - -export async function runDockerBuild( - buildStore: BuildStore, - serverUrl: string, - buildId: string, -): Promise { - const build = buildStore.getBuild(buildId); - if (!build) { - throw new Error(`Build ${buildId} not found`); - } - - const contextUrl = `${serverUrl}/builds/${buildId}/kaniko/context.tar.gz`; - const outputUrl = `${serverUrl}/builds/${buildId}/kaniko/output.tar.gz`; - - const kanikoArgs = [ - "run", - "--rm", - "--network=host", - "-e", - `KANIKO_ARGS=${serializeKanikoArguments({ - contextUrl, - outputUrl, - destination: `${buildId}:latest`, - dockerfilePath: build.dockerfilePath, - buildArgs: build.buildArgs, - buildTarget: build.buildTarget, - })}`, - "ci-runner", - ]; - - buildStore.addLog( - buildId, - `Starting kaniko with args: docker ${kanikoArgs.join(" ")}`, - ); - - buildStore.updateStatus(buildId, { - type: "running", - data: { docker: {} }, - }); - - return new Promise((resolve, reject) => { - const dockerProcess = spawn("docker", kanikoArgs, { - stdio: ["pipe", "pipe", "pipe"], - }); - - buildStore.setContainerProcess(buildId, dockerProcess); - - dockerProcess.stdout?.on("data", (data) => { - const lines = data - .toString() - .split("\n") - .filter((line: string) => line.trim()); - lines.forEach((line: string) => { - buildStore.addLog(buildId, `[kaniko] ${line}`); - }); - }); - - dockerProcess.stderr?.on("data", (data) => { - const lines = data - .toString() - .split("\n") - .filter((line: string) => line.trim()); - lines.forEach((line: string) => { - buildStore.addLog(buildId, `[kaniko-error] ${line}`); - }); - }); - - dockerProcess.on("close", (code) => { - buildStore.addLog( - buildId, - `Docker process closed with exit code: ${code}`, - ); - buildStore.updateStatus(buildId, { type: "finishing", data: {} }); - - if (code === 0) { - resolve(); - } else { - buildStore.updateStatus(buildId, { - type: "failure", - data: { reason: `Container exited with code ${code}` }, - }); - reject(new Error(`Container exited with code ${code}`)); - } - }); - - dockerProcess.on("spawn", () => { - buildStore.addLog(buildId, "Docker process spawned successfully"); - }); - - dockerProcess.on("error", (error) => { - buildStore.addLog( - buildId, - `Docker process error: ${error.message}`, - ); - buildStore.updateStatus(buildId, { - type: "failure", - data: { reason: `Failed to start kaniko: ${error.message}` }, - }); - reject(error); - }); - }); -} diff --git a/cloud/packages/ci-manager/src/executors/rivet.ts b/cloud/packages/ci-manager/src/executors/rivet.ts deleted file mode 100644 index 7cf54b8812..0000000000 --- a/cloud/packages/ci-manager/src/executors/rivet.ts +++ /dev/null @@ -1,184 +0,0 @@ -import { RivetClient } from "@rivet-gg/api"; -import type { BuildStore } from "../build-store"; -import { serializeKanikoArguments } from "../common"; - -export async function runRivetBuild( - buildStore: BuildStore, - serverUrl: string, - buildId: string, -): Promise { - const token = process.env.RIVET_CLOUD_TOKEN; - if (!token) { - throw new Error("RIVET_CLOUD_TOKEN environment variable is required"); - } - - const projectId = process.env.RIVET_PROJECT!; - if (!projectId) { - throw new Error("RIVET_PROJECT environment variable is required"); - } - - const environmentName = process.env.RIVET_ENVIRONMENT!; - if (!environmentName) { - throw new Error("RIVET_ENVIRONMENT environment variable is required"); - } - - const kanikoBuildId = process.env.KANIKO_BUILD_ID!; - if (!kanikoBuildId) { - throw new Error("KANIKO_BUILD_ID environment variable is required"); - } - - const client = new RivetClient({ token }); - - const build = buildStore.getBuild(buildId); - if (!build) { - throw new Error(`Build ${buildId} not found`); - } - - const contextUrl = `${serverUrl}/builds/${buildId}/kaniko/context.tar.gz`; - const outputUrl = `${serverUrl}/builds/${buildId}/kaniko/output.tar.gz`; - - buildStore.addLog(buildId, "Creating Rivet actor for kaniko build..."); - - try { - const createResponse = await client.actors.create({ - project: projectId, - environment: environmentName, - body: { - tags: { - name: "ci-runner", - }, - build: kanikoBuildId, - runtime: { - environment: { - KANIKO_ARGS: serializeKanikoArguments({ - contextUrl, - outputUrl, - destination: `${buildId}:latest`, - dockerfilePath: build.dockerfilePath, - buildArgs: build.buildArgs, - buildTarget: build.buildTarget, - }), - }, - }, - network: { - ports: {}, - waitReady: false, - }, - resources: { - cpu: 1000, - memory: 1024, - }, - lifecycle: { - killTimeout: 300000, - durable: false, - }, - }, - }); - - const actorId = createResponse.actor.id; - buildStore.addLog(buildId, `Created Rivet actor: ${actorId}`); - - buildStore.updateStatus(buildId, { - type: "running", - data: { - rivet: { actorId }, - }, - }); - - await pollActorStatus( - buildStore, - client, - projectId, - environmentName, - buildId, - actorId, - ); - } catch (error: any) { - buildStore.addLog( - buildId, - `Failed to create Rivet actor: ${error.message}`, - ); - buildStore.updateStatus(buildId, { - type: "failure", - data: { reason: `Failed to create Rivet actor: ${error.message}` }, - }); - } -} - -async function pollActorStatus( - buildStore: BuildStore, - client: RivetClient, - projectId: string, - environmentName: string, - buildId: string, - actorId: string, -): Promise { - const pollInterval = 2000; - const maxPolls = 300; - let pollCount = 0; - - while (true) { - try { - pollCount++; - if (pollCount > maxPolls) { - buildStore.addLog(buildId, "Polling timeout reached"); - buildStore.updateStatus(buildId, { - type: "failure", - data: { reason: "Actor polling timeout" }, - }); - return; - } - - const { actor } = await client.actors.get(actorId, { - project: projectId, - environment: environmentName, - }); - - let state: string; - if (actor.destroyedAt && actor.startedAt) { - if (actor.startedAt) { - state = "stopped"; - } else { - state = "crashed"; - } - } else if (actor.startedAt) { - state = "running"; - } else { - state = "starting"; - } - - buildStore.addLog(buildId, `Actor status: ${state}`); - - if (state === "stopped") { - buildStore.addLog(buildId, `Actor stopped.`); - return; - } - - if (state === "crashed") { - buildStore.updateStatus(buildId, { - type: "failure", - data: { reason: `Actor crashed` }, - }); - return; - } - - if (state === "running" || state === "starting") { - await new Promise((resolve) => setTimeout(resolve, 1000)); - } else { - buildStore.addLog(buildId, `Unexpected actor state: ${state}`); - buildStore.updateStatus(buildId, { - type: "failure", - data: { reason: `Unexpected actor state: ${state}` }, - }); - return; - } - } catch (error: any) { - buildStore.addLog(buildId, `Error polling actor: ${error.message}`); - buildStore.updateStatus(buildId, { - type: "failure", - data: { reason: `Error polling actor: ${error.message}` }, - }); - return; - } - } -} diff --git a/cloud/packages/ci-manager/src/index.ts b/cloud/packages/ci-manager/src/index.ts deleted file mode 100644 index 5720134d1f..0000000000 --- a/cloud/packages/ci-manager/src/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { createServer } from "./server"; - -console.log("CI Manager starting on port 3000"); -createServer(3000); diff --git a/cloud/packages/ci-manager/src/kaniko-runner.ts b/cloud/packages/ci-manager/src/kaniko-runner.ts deleted file mode 100644 index 0cd4358034..0000000000 --- a/cloud/packages/ci-manager/src/kaniko-runner.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { existsSync } from "node:fs"; -import { mkdir } from "node:fs/promises"; -import { dirname } from "node:path"; -import type { BuildStore } from "./build-store"; -import { runDockerBuild } from "./executors/docker"; -import { runRivetBuild } from "./executors/rivet"; - -export async function runKanikoBuild( - buildStore: BuildStore, - serverUrl: string, - buildId: string, -): Promise { - const build = buildStore.getBuild(buildId); - if (!build) { - throw new Error(`Build ${buildId} not found`); - } - - await mkdir(dirname(build.contextPath!), { recursive: true }); - - buildStore.updateStatus(buildId, { - type: "running", - data: { - noRunner: {}, - }, - }); - - const executionMode = process.env.KANIKO_EXECUTION_MODE || "docker"; - buildStore.addLog(buildId, `Using execution mode: ${executionMode}`); - - if (executionMode === "rivet") { - await runRivetBuild(buildStore, serverUrl, buildId); - } else { - await runDockerBuild(buildStore, serverUrl, buildId); - } - - // Add upload validation check - await validateBuildUpload(buildStore, buildId); -} - -async function validateBuildUpload( - buildStore: BuildStore, - buildId: string, -): Promise { - const build = buildStore.getBuild(buildId); - if (!build) { - buildStore.updateStatus(buildId, { - type: "failure", - data: { reason: "Build not found" }, - }); - return; - } - - if (existsSync(build.outputPath)) { - buildStore.addLog(buildId, "Build upload validated successfully"); - } else { - buildStore.updateStatus(buildId, { - type: "failure", - data: { - reason: "Build output file was not uploaded after waiting", - }, - }); - } -} diff --git a/cloud/packages/ci-manager/src/oci-converter.ts b/cloud/packages/ci-manager/src/oci-converter.ts deleted file mode 100644 index 0f97e7220e..0000000000 --- a/cloud/packages/ci-manager/src/oci-converter.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { execSync } from "child_process"; -import { join } from "path"; -import { mkdir, readFile, rm, writeFile } from "fs/promises"; -import * as tar from "tar"; - -export interface OCIConversionResult { - bundleTarPath: string; - cleanup: () => Promise; -} - -export async function convertDockerTarToOCIBundle( - dockerTarPath: string, - tempDir = "/tmp/oci-conversion", -): Promise { - const conversionId = Math.random().toString(36).substring(7); - const workDir = join(tempDir, conversionId); - - try { - await mkdir(workDir, { recursive: true }); - - const dockerImagePath = join(workDir, "docker-image.tar"); - const ociImagePath = join(workDir, "oci-image"); - const ociBundlePath = join(workDir, "oci-bundle"); - const bundleTarPath = join(workDir, "oci-bundle.tar"); - - // Extract docker tar if it's compressed - const dockerTarData = await readFile(dockerTarPath); - await writeFile(dockerImagePath, dockerTarData); - - // Convert Docker image to OCI image using skopeo - console.log( - `Converting Docker image to OCI image: ${dockerImagePath} -> ${ociImagePath}`, - ); - execSync( - `skopeo copy docker-archive:${dockerImagePath} oci:${ociImagePath}:default`, - { - stdio: "pipe", - }, - ); - - // Convert OCI image to OCI bundle using umoci - console.log( - `Converting OCI image to OCI bundle: ${ociImagePath} -> ${ociBundlePath}`, - ); - execSync( - `umoci unpack --rootless --image ${ociImagePath}:default ${ociBundlePath}`, - { - stdio: "pipe", - }, - ); - - // Create tar from OCI bundle - console.log( - `Creating tar from OCI bundle: ${ociBundlePath} -> ${bundleTarPath}`, - ); - await tar.create( - { - file: bundleTarPath, - cwd: ociBundlePath, - }, - ["."], - ); - - // Clean up intermediate files - await Promise.all([ - rm(dockerImagePath, { force: true }), - rm(ociImagePath, { recursive: true, force: true }), - rm(ociBundlePath, { recursive: true, force: true }), - ]); - - const cleanup = async () => { - try { - await rm(workDir, { recursive: true, force: true }); - } catch (error) { - console.warn( - `Failed to cleanup OCI conversion directory ${workDir}:`, - error, - ); - } - }; - - return { - bundleTarPath, - cleanup, - }; - } catch (error) { - // Cleanup on error - try { - await rm(workDir, { recursive: true, force: true }); - } catch (cleanupError) { - console.warn( - `Failed to cleanup after error in ${workDir}:`, - cleanupError, - ); - } - throw new Error(`OCI conversion failed: ${error}`); - } -} diff --git a/cloud/packages/ci-manager/src/rivet-uploader.ts b/cloud/packages/ci-manager/src/rivet-uploader.ts deleted file mode 100644 index d9c8c6ed1e..0000000000 --- a/cloud/packages/ci-manager/src/rivet-uploader.ts +++ /dev/null @@ -1,232 +0,0 @@ -import { statSync } from "fs"; -import { RivetClient } from "@rivet-gg/api"; - -export interface RivetUploadConfig { - token: string; - project?: string; - environment?: string; -} - -export interface RivetUploadResult { - buildId: string; -} - -export async function uploadOCIBundleToRivet( - bundleTarPath: string, - buildName: string, - imageTag: string, - config: RivetUploadConfig, - buildVersion: string, - extraTags?: Record, -): Promise { - const client = new RivetClient({ token: config.token }); - - try { - // Get file stats - const stats = statSync(bundleTarPath); - const fileSize = stats.size; - - console.log( - `Preparing Rivet upload for ${bundleTarPath} (${fileSize} bytes)`, - ); - - // Prepare the build upload - const prepareResponse = await client.builds.prepare({ - project: config.project, - environment: config.environment, - body: { - imageTag, - imageFile: { - path: "oci-bundle.tar", - contentType: "application/x-tar", - contentLength: fileSize, - }, - kind: "oci_bundle", - compression: "none", - }, - }); - - const buildId = prepareResponse.build; - const presignedRequests = prepareResponse.presignedRequests; - - console.log(`Rivet build prepared: ${buildId}`); - console.log(`Upload chunks: ${presignedRequests.length}`); - - // Upload chunks in parallel - const uploadPromises = presignedRequests.map(async (request, index) => { - const { url, byteOffset, contentLength } = request; - - console.log( - `Uploading chunk ${index + 1}/${presignedRequests.length}: offset=${byteOffset}, size=${contentLength}`, - ); - - // Read the specific chunk - const buffer = Buffer.alloc(contentLength); - const fileHandle = await import("fs/promises").then((fs) => - fs.open(bundleTarPath, "r"), - ); - try { - await fileHandle.read(buffer, 0, contentLength, byteOffset); - } finally { - await fileHandle.close(); - } - - // Upload chunk with retries - await uploadChunkWithRetry(url, buffer, 3); - - console.log( - `Chunk ${index + 1}/${presignedRequests.length} uploaded successfully`, - ); - }); - - // Wait for all chunks to upload - await Promise.all(uploadPromises); - - console.log(`All chunks uploaded for build ${buildId}`); - - // Complete the build - await client.builds.complete(buildId, { - project: config.project, - environment: config.environment, - }); - - console.log(`Rivet build completed: ${buildId}`); - - // Patch tags: remove "current" from existing builds with same name, then set current on new build - await patchBuildTags( - client, - buildId, - buildName, - config, - buildVersion, - extraTags, - ); - - return { buildId }; - } catch (error) { - throw new Error(`Rivet upload failed: ${error}`); - } -} - -async function uploadChunkWithRetry( - url: string, - buffer: Buffer, - maxRetries = 3, -): Promise { - let lastError: Error | null = null; - - for (let attempt = 1; attempt <= maxRetries; attempt++) { - try { - const response = await fetch(url, { - method: "PUT", - body: buffer, - headers: { - "Content-Type": "application/octet-stream", - "Content-Length": buffer.length.toString(), - }, - }); - - if (!response.ok) { - throw new Error( - `HTTP ${response.status}: ${response.statusText}`, - ); - } - - return; // Success - } catch (error) { - lastError = - error instanceof Error ? error : new Error(String(error)); - console.warn( - `Upload attempt ${attempt}/${maxRetries} failed:`, - lastError.message, - ); - - if (attempt < maxRetries) { - // Exponential backoff: 1s, 2s, 4s - const delay = Math.pow(2, attempt - 1) * 1000; - await new Promise((resolve) => setTimeout(resolve, delay)); - } - } - } - - throw new Error( - `Upload failed after ${maxRetries} attempts: ${lastError?.message}`, - ); -} - -async function patchBuildTags( - client: RivetClient, - buildId: string, - buildName: string, - config: RivetUploadConfig, - buildVersion: string, - extraTags?: Record, -): Promise { - try { - console.log( - `Patching tags for build ${buildId} with name: ${buildName}`, - ); - - // Step 1: Find existing builds with the same name and current=true - const tagsFilter = JSON.stringify({ - name: buildName, - current: "true", - }); - - const listResponse = await client.builds.list({ - project: config.project, - environment: config.environment, - tagsJson: tagsFilter, - }); - - console.log( - `Found ${listResponse.builds.length} existing builds with current tag`, - ); - - // Step 2: Remove "current" tag from all existing builds with the same name - for (const build of listResponse.builds) { - try { - await client.builds.patchTags(build.id, { - project: config.project, - environment: config.environment, - body: { - tags: { - current: null, - }, - }, - }); - console.log(`Removed current tag from build ${build.id}`); - } catch (error) { - console.warn( - `Failed to remove current tag from build ${build.id}:`, - error, - ); - } - } - - // Step 3: Set tags on the new build - const tags: Record = { - name: buildName, - version: buildVersion, - current: "true", - }; - - // Add extra tags if provided - if (extraTags) { - Object.assign(tags, extraTags); - } - - await client.builds.patchTags(buildId, { - project: config.project, - environment: config.environment, - body: { - tags, - }, - }); - - console.log(`Successfully patched tags for build ${buildId}`); - } catch (error) { - console.warn(`Failed to patch tags for build ${buildId}:`, error); - // Don't throw here to avoid failing the entire upload process - } -} diff --git a/cloud/packages/ci-manager/src/server.ts b/cloud/packages/ci-manager/src/server.ts deleted file mode 100644 index 384a352a7e..0000000000 --- a/cloud/packages/ci-manager/src/server.ts +++ /dev/null @@ -1,319 +0,0 @@ -import { createReadStream, createWriteStream } from "node:fs"; -import { mkdir, stat } from "node:fs/promises"; -import { Readable } from "node:stream"; -import { pipeline } from "node:stream/promises"; -import { dirname } from "path"; -import { serve } from "@hono/node-server"; -import { Hono } from "hono"; -import { logger } from "hono/logger"; -import { streamSSE } from "hono/streaming"; -import type { ReadableStream as WebReadableStream } from "stream/web"; -import { BuildStore } from "./build-store"; -import { runKanikoBuild } from "./kaniko-runner"; -import { convertDockerTarToOCIBundle } from "./oci-converter"; -import { - type RivetUploadConfig, - uploadOCIBundleToRivet, -} from "./rivet-uploader"; -import { BuildRequestSchema } from "./types"; - -async function processRivetUpload( - buildStore: BuildStore, - buildId: string, -): Promise { - const build = buildStore.getBuild(buildId); - if (!build) { - throw new Error(`Build ${buildId} not found`); - } - - try { - // Check if Rivet upload is enabled - const rivetToken = process.env.RIVET_CLOUD_TOKEN; - const rivetProject = process.env.RIVET_PROJECT; - const rivetEnvironment = process.env.RIVET_ENVIRONMENT; - - if (!rivetToken || !rivetProject || !rivetEnvironment) { - throw new Error( - "Rivet upload failed - missing RIVET_CLOUD_TOKEN, RIVET_PROJECT, or RIVET_ENVIRONMENT", - ); - } - - const rivetConfig: RivetUploadConfig = { - token: rivetToken, - project: rivetProject, - environment: build.environmentId, - }; - - // Step 1: Convert to OCI bundle - buildStore.updateStatus(buildId, { type: "converting", data: {} }); - buildStore.addLog(buildId, "Converting Docker image to OCI bundle..."); - - const conversionResult = await convertDockerTarToOCIBundle( - build.outputPath, - ); - - try { - // Step 2: Upload to Rivet - buildStore.updateStatus(buildId, { - type: "uploading", - data: {}, - }); - buildStore.addLog(buildId, "Uploading OCI bundle to Rivet..."); - - const uploadResult = await uploadOCIBundleToRivet( - conversionResult.bundleTarPath, - build.buildName, - `${buildId}:latest`, // Match kaniko destination format - rivetConfig, - new Date().toISOString(), // Use timestamp as version for now - ); - - buildStore.addLog( - buildId, - `Successfully uploaded to Rivet: ${uploadResult.buildId}`, - ); - buildStore.updateStatus(buildId, { - type: "success", - data: { buildId: uploadResult.buildId }, - }); - } finally { - await conversionResult.cleanup(); - } - } catch (error) { - buildStore.updateStatus(buildId, { - type: "failure", - data: { reason: `Rivet upload process failed: ${error}` }, - }); - buildStore.addLog(buildId, `Rivet upload process failed: ${error}`); - throw error; - } -} - -export async function createServer(port = 3000) { - const app = new Hono(); - - app.use(logger()); - - const buildStore = new BuildStore(); - await buildStore.init(); - - app.post("/builds", async (c) => { - try { - const body = await c.req.parseBody(); - const parseResult = BuildRequestSchema.safeParse(body); - if (!parseResult.success) { - return c.json({ error: "Invalid build request format" }, 400); - } - const { - buildName, - dockerfilePath, - environmentId, - buildArgs, - buildTarget, - context: contextFile, - } = parseResult.data; - - // Create the build - const buildId = buildStore.createBuild( - buildName, - dockerfilePath, - environmentId, - buildArgs, - buildTarget, - ); - const contextPath = buildStore.getContextPath(buildId); - - if (!contextPath) { - return c.json({ error: "Failed to create build" }, 500); - } - - // Save the context file - await mkdir(dirname(contextPath), { recursive: true }); - - const contextBuffer = await contextFile.arrayBuffer(); - const fileStream = createWriteStream(contextPath); - fileStream.write(new Uint8Array(contextBuffer)); - fileStream.end(); - - buildStore.addLog(buildId, "Context uploaded successfully"); - - // Run build in background - buildStore.addLog(buildId, "About to start kaniko runner"); - - const serverUrlParam = c.req.query("serverUrl"); - const serverUrl = serverUrlParam || new URL(c.req.url).origin; - buildStore.addLog(buildId, `Using server URL: ${serverUrl}`); - - try { - runKanikoBuild(buildStore, serverUrl, buildId).catch( - (error) => { - buildStore.addLog( - buildId, - `Failed to start build: ${error}`, - ); - buildStore.updateStatus(buildId, { - type: "failure", - data: { reason: `Failed to start build: ${error}` }, - }); - }, - ); - } catch (error) { - buildStore.addLog( - buildId, - `Sync error starting build: ${error}`, - ); - } - - return c.json({ buildId }); - } catch (error) { - console.error("Error processing build request:", error); - return c.json({ error: "Failed to process build request" }, 500); - } - }); - - app.get("/builds/:id", async (c) => { - const buildId = c.req.param("id"); - const build = buildStore.getBuild(buildId); - - if (!build) { - return c.json({ error: "Build not found" }, 404); - } - - return c.json({ - id: build.id, - status: build.status, - }); - }); - - app.get("/builds/:id/events", async (c) => { - const buildId = c.req.param("id"); - const build = buildStore.getBuild(buildId); - - if (!build) { - return c.json({ error: "Build not found" }, 404); - } - - return streamSSE(c, async (stream) => { - await stream.writeSSE({ data: "connected" }); - - for (const event of build.events) { - await stream.writeSSE({ data: JSON.stringify(event) }); - } - - const unsubscribe = buildStore.emitter.on( - "build-event", - async (eventBuildId, event) => { - if (eventBuildId === buildId) { - await stream.writeSSE({ data: JSON.stringify(event) }); - } - }, - ); - - let resolve: () => void; - const abortPromise = new Promise((res) => { - resolve = res; - }); - - stream.onAbort(() => { - unsubscribe(); - resolve(); - }); - - await abortPromise; - }); - }); - - app.get("/builds/:id/kaniko/context.tar.gz", async (c) => { - const buildId = c.req.param("id"); - console.log(`[SERVER] Kaniko requesting context for build ${buildId}`); - const contextPath = buildStore.getContextPath(buildId); - - if (!contextPath) { - return c.json({ error: "Build not found" }, 404); - } - - try { - const fileStream = createReadStream(contextPath); - return new Response(fileStream as any, { - headers: { - "content-type": "application/gzip", - "content-disposition": - "attachment; filename=context.tar.gz", - }, - }); - } catch (error) { - return c.json({ error: "Context file not found" }, 404); - } - }); - - app.get("/builds/:id/output.tar.gz", async (c) => { - const buildId = c.req.param("id"); - const outputPath = buildStore.getOutputPath(buildId); - - if (!outputPath) { - return c.json({ error: "Build not found" }, 404); - } - - try { - const fileStream = createReadStream(outputPath); - - // Mark as downloaded to trigger cleanup - buildStore.markDownloaded(buildId); - - return new Response(fileStream as any, { - headers: { - "content-type": "application/gzip", - "content-disposition": "attachment; filename=output.tar.gz", - }, - }); - } catch (error) { - return c.json({ error: "Output file not found" }, 404); - } - }); - - app.put("/builds/:id/kaniko/output.tar.gz", async (c) => { - const buildId = c.req.param("id"); - console.log(`[SERVER] Kaniko uploading output for build ${buildId}`); - const outputPath = buildStore.getOutputPath(buildId); - - if (!outputPath) { - return c.json({ error: "Build not found" }, 404); - } - - try { - await mkdir(dirname(outputPath), { recursive: true }); - - const body = c.req.raw.body; - if (!body) return c.json({ error: "Body does not exist" }, 400); - - const nodeStream = Readable.fromWeb(body as WebReadableStream); - const writeStream = createWriteStream(outputPath); - await pipeline(nodeStream, writeStream); - - // Log upload details - const stats = await stat(outputPath); - buildStore.addLog( - buildId, - `Kaniko output uploaded successfully: ${outputPath} (${stats.size} bytes)`, - ); - - // Start Rivet upload process in background - processRivetUpload(buildStore, buildId).catch((error) => { - buildStore.addLog(buildId, `Rivet upload failed: ${error}`); - buildStore.updateStatus(buildId, { - type: "failure", - data: { reason: `Rivet upload failed: ${error}` }, - }); - }); - - return c.json({ message: "File saved successfully" }); - } catch (error) { - return c.json({ error: "Failed to create output file" }, 500); - } - }); - - return serve({ - fetch: app.fetch, - port, - }); -} diff --git a/cloud/packages/ci-manager/src/types.ts b/cloud/packages/ci-manager/src/types.ts deleted file mode 100644 index 6519ec6099..0000000000 --- a/cloud/packages/ci-manager/src/types.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { z } from "zod"; -import { NO_SEP_CHAR_REGEX, UNIT_SEP_CHAR } from "./common"; - -export const RunnerSchema = z.union([ - z.object({ - rivet: z.object({ - actorId: z.string(), - }), - }), - z.object({ - docker: z.object({}), - }), - z.object({ - noRunner: z.object({}), - }), -]); - -export type Runner = z.infer; - -export const StatusSchema = z.discriminatedUnion("type", [ - z.object({ type: z.literal("starting"), data: z.object({}) }), - z.object({ type: z.literal("running"), data: RunnerSchema }), - z.object({ type: z.literal("finishing"), data: z.object({}) }), - z.object({ type: z.literal("converting"), data: z.object({}) }), - z.object({ type: z.literal("uploading"), data: z.object({}) }), - z.object({ - type: z.literal("failure"), - data: z.object({ reason: z.string() }), - }), - z.object({ - type: z.literal("success"), - data: z.object({ buildId: z.string() }), - }), -]); - -export type Status = z.infer; - -const ILLEGAL_BUILD_ARG_KEY = /[\s'"\\]/g; -const BuildArgsSchema = z - .string() - .transform((str) => JSON.parse(str)) - .pipe(z.array(z.string())) - .refine( - (arr) => { - // Check each key=value pair to ensure keys have no spaces - return arr.every((item) => { - const [key] = item.split("="); - if (!key) return false; - if (ILLEGAL_BUILD_ARG_KEY.test(key)) return false; - if (item.includes(UNIT_SEP_CHAR)) return false; - return true; - }); - }, - { message: "Argument key/value contains invalid character" }, - ) - .transform((arr) => { - const result: Record = Object.create(null); - // Convert array of strings to an object - for (const item of arr) { - const [key, ...valueParts] = item.split("="); - const value = valueParts.join("="); - - if (key && value !== undefined) { - result[key] = value; - } - } - - return result; - }); - -export const BuildRequestSchema = z.object({ - buildName: z - .string() - .regex( - NO_SEP_CHAR_REGEX, - "buildName cannot contain special characters", - ), - dockerfilePath: z - .string() - .regex( - NO_SEP_CHAR_REGEX, - "dockerfilePath cannot contain special characters", - ), - environmentId: z - .string() - .regex( - NO_SEP_CHAR_REGEX, - "environmentId cannot contain special characters", - ), - buildArgs: BuildArgsSchema, - buildTarget: z - .string() - .regex( - NO_SEP_CHAR_REGEX, - "buildTarget cannot contain special characters", - ) - .optional(), - context: z.instanceof(File), -}); - -export type BuildRequest = z.infer; - -export const BuildEventSchema = z.discriminatedUnion("type", [ - z.object({ type: z.literal("status"), data: StatusSchema }), - z.object({ type: z.literal("log"), data: z.object({ line: z.string() }) }), -]); - -export type BuildEvent = z.infer; - -export interface BuildInfo { - id: string; - status: Status; - buildName: string; - dockerfilePath: string; - environmentId: string; - contextPath: string; - buildArgs: Record; - buildTarget?: string; - outputPath: string; - events: BuildEvent[]; - containerProcess?: any; - createdAt: Date; - downloadedAt?: Date; - cleanupTimeout?: NodeJS.Timeout; -} diff --git a/cloud/packages/ci-manager/tests/docker-e2e.test.ts b/cloud/packages/ci-manager/tests/docker-e2e.test.ts deleted file mode 100644 index 2fbef9f1be..0000000000 --- a/cloud/packages/ci-manager/tests/docker-e2e.test.ts +++ /dev/null @@ -1,219 +0,0 @@ -/** - * This test is intended to check that Kaniko works as intended with an inline driver (not using Rivet). - * - * Useful for quick iteration on the server. - */ - -import { execSync } from "node:child_process"; -import { join } from "node:path"; -import { RivetClient } from "@rivet-gg/api"; -import getPort from "get-port"; -import { afterAll, beforeAll, describe, expect, it } from "vitest"; -import type { RivetUploadConfig } from "../src/rivet-uploader"; -import { createServer } from "../src/server"; -import { - createActorFromBuild, - createBuildWithContext, - createFailingDockerContext, - createTestWebServerContext, - getBuildStatus, - pollBuildStatus, - testActorEndpoint, -} from "./test-utils"; - -describe("Docker", () => { - let server: any; - let baseUrl: string; - let rivetConfig: RivetUploadConfig = undefined as any; - const testActorIds: string[] = []; - - beforeAll(async () => { - // Build the ci-manager dockerfile before starting tests - console.log("Building ci-runner Docker image..."); - execSync("docker build -t ci-runner .", { - cwd: join(__dirname, "../../ci-runner"), - stdio: "inherit", - }); - console.log("ci-runner Docker image built successfully"); - - const port = await getPort(); - server = await createServer(port); - baseUrl = `http://localhost:${port}`; - - // Initialize Rivet config if environment variables are available - const token = process.env.RIVET_CLOUD_TOKEN; - const project = process.env.RIVET_PROJECT; - const environment = process.env.RIVET_ENVIRONMENT; - - if (token && project && environment) { - rivetConfig = { token, project, environment }; - console.log("Rivet config initialized - will test actor creation"); - } else { - throw new Error( - "Rivet config not available - skipping actor creation tests", - ); - } - }); - - afterAll(async () => { - // Clean up test actors - const client = new RivetClient({ token: rivetConfig.token }); - for (const actorId of testActorIds) { - try { - await client.actors.destroy(actorId, { - project: rivetConfig.project, - environment: rivetConfig.environment, - }); - console.log(`Cleaned up test actor: ${actorId}`); - } catch (error) { - console.warn(`Failed to cleanup test actor ${actorId}:`, error); - } - } - - if (server) { - if (typeof server.stop === "function") { - server.stop(); - } else if (typeof server.close === "function") { - server.close(); - } - } - }); - - it("full e2e", async () => { - console.log("Starting E2E CI Manager Test"); - - // Create sample Docker context with web server - console.log("Creating sample Docker context with web server..."); - const contextBuffer = await createTestWebServerContext(); - console.log(`Context created (${contextBuffer.length} bytes)`); - expect(contextBuffer.length).toBeGreaterThan(0); - - // Create build with context - console.log("Creating build with context..."); - const buildName = "test-build-" + Date.now(); - const buildId = await createBuildWithContext( - baseUrl, - buildName, - "configs/build.dockerfile", - contextBuffer, - rivetConfig.environment, - ); - console.log(`Build created and started: ${buildId}`); - expect(buildId).toBeDefined(); - expect(typeof buildId).toBe("string"); - - // Poll build status until completion - console.log("Polling build status..."); - const buildResult = await pollBuildStatus(baseUrl, buildId); - console.log(`Build completed with status: ${buildResult.status}`); - - // The build should actually succeed since we have Kaniko available - expect(buildResult.status).toBe("success"); - - console.log("Build completed successfully!"); - - // Get final build status - console.log("Checking final build status:"); - const buildStatus = await getBuildStatus(baseUrl, buildId); - console.log(buildStatus); - expect(buildStatus.id).toBe(buildId); - expect(buildStatus.status.type).toBe("success"); - - let actorId: string | undefined; - - // Create actor from build - console.log("Creating actor from build..."); - const actorResult = await createActorFromBuild( - buildResult.buildId, - buildName, - rivetConfig, - ); - - actorId = actorResult.actorId; - testActorIds.push(actorId); - - expect(actorResult.endpoint).toBeDefined(); - - console.log(`Actor created: ${actorId}`); - console.log(`Actor endpoint: ${actorResult.endpoint}`); - - // Wait for actor to be ready and test endpoint - console.log("Testing actor HTTP endpoint..."); - const testResponse = await testActorEndpoint(actorResult.endpoint); - - expect(testResponse).toBeDefined(); - expect(testResponse.message).toBe("Rivet test successful!"); - expect(testResponse.timestamp).toBeDefined(); - expect(testResponse.hostname).toBeDefined(); - - console.log("E2E Test completed successfully!"); - }, 600000); // Increase timeout to 10 minutes for the full workflow including Rivet - - it("should handle build not found", async () => { - const response = await fetch(`${baseUrl}/builds/non-existent-build`); - expect(response.status).toBe(404); - - const result = await response.json(); - expect(result.error).toBe("Build not found"); - }); - - it("should reject build creation with missing data", async () => { - const formData = new FormData(); - formData.append("buildName", "test-build"); - // Missing dockerfilePath and context file - - const response = await fetch(`${baseUrl}/builds`, { - method: "POST", - body: formData, - }); - - expect(response.status).toBe(400); - - const result = await response.json(); - expect(result.error).toBe("dockerfilePath is required"); - }); - - it("should handle failing dockerfile build correctly", async () => { - console.log("Starting failing dockerfile test"); - - // Create failing Docker context - console.log("Creating failing Docker context..."); - const contextBuffer = await createFailingDockerContext(); - console.log(`Failing context created (${contextBuffer.length} bytes)`); - expect(contextBuffer.length).toBeGreaterThan(0); - - // Create build with failing context - console.log("Creating build with failing context..."); - const buildName = "test-failing-build-" + Date.now(); - const buildId = await createBuildWithContext( - baseUrl, - buildName, - "configs/fail.dockerfile", - contextBuffer, - rivetConfig.environment, - ); - console.log(`Failing build created: ${buildId}`); - expect(buildId).toBeTruthy(); - - // Poll build status until failure - console.log("Polling build status for failure..."); - const buildResult = await pollBuildStatus(baseUrl, buildId); - console.log(`Build completed with status: ${buildResult.status}`); - - // Verify build completed with failure status - expect(buildResult.status).toBe("failure"); - - // Check final build status via API - console.log("Checking final build status:"); - const buildStatus = await getBuildStatus(baseUrl, buildId); - console.log(buildStatus); - expect(buildStatus.id).toBe(buildId); - expect(buildStatus.status.type).toBe("failure"); - - // Get final build status to verify failure reason - const finalBuildStatus = await getBuildStatus(baseUrl, buildId); - expect(finalBuildStatus.status.data.reason).toBeTruthy(); - - console.log("Failing dockerfile test completed successfully!"); - }, 70000); // 70 second timeout for failing build test -}); diff --git a/cloud/packages/ci-manager/tests/oci-converter.test.ts b/cloud/packages/ci-manager/tests/oci-converter.test.ts deleted file mode 100644 index d3ac999229..0000000000 --- a/cloud/packages/ci-manager/tests/oci-converter.test.ts +++ /dev/null @@ -1,219 +0,0 @@ -import { execSync } from "child_process"; -import { join } from "path"; -import { mkdir, readFile, rm, writeFile } from "fs/promises"; -import * as tar from "tar"; -import { afterAll, beforeAll, expect, test } from "vitest"; -import { convertDockerTarToOCIBundle } from "../src/oci-converter"; - -const TEST_DIR = "/tmp/oci-converter-test"; -const TEST_IMAGE_NAME = "oci-converter-test"; - -async function createTestDockerImage(): Promise { - const contextDir = join(TEST_DIR, "docker-context"); - await mkdir(contextDir, { recursive: true }); - - // Create a simple Dockerfile - const dockerfile = ` -FROM alpine:latest -RUN echo "Hello from OCI converter test!" > /hello.txt -COPY test-script.sh /test-script.sh -RUN chmod +x /test-script.sh -CMD ["/test-script.sh"] -`; - - // Create a test script - const testScript = `#!/bin/sh -echo "OCI conversion test successful!" -cat /hello.txt -`; - - await writeFile(join(contextDir, "Dockerfile"), dockerfile.trim()); - await writeFile(join(contextDir, "test-script.sh"), testScript.trim()); - - // Build the Docker image - console.log(`Building test Docker image: ${TEST_IMAGE_NAME}`); - execSync(`docker build -t ${TEST_IMAGE_NAME} .`, { - cwd: contextDir, - stdio: "pipe", - }); - - // Save the Docker image to tar - const dockerTarPath = join(TEST_DIR, "test-image.tar"); - console.log(`Saving Docker image to: ${dockerTarPath}`); - execSync(`docker save -o ${dockerTarPath} ${TEST_IMAGE_NAME}`, { - stdio: "pipe", - }); - - return dockerTarPath; -} - -async function createMockKanikoOutput(dockerTarPath: string): Promise { - const kanikoOutputPath = join(TEST_DIR, "kaniko-output.tar.gz"); - const tempDir = join(TEST_DIR, "kaniko-temp"); - - await mkdir(tempDir, { recursive: true }); - - // Copy docker tar to the expected location inside kaniko output - const dockerTarData = await readFile(dockerTarPath); - await writeFile(join(tempDir, "image.tar"), dockerTarData); - - // Create kaniko output tar.gz - await tar.create( - { - file: kanikoOutputPath, - gzip: true, - cwd: tempDir, - }, - ["."], - ); - - // Cleanup temp directory - await rm(tempDir, { recursive: true, force: true }); - - return kanikoOutputPath; -} - -async function validateOCIBundle(bundleTarPath: string): Promise { - const validateDir = join(TEST_DIR, "validate"); - await mkdir(validateDir, { recursive: true }); - - try { - // Extract the OCI bundle tar - await tar.extract({ - file: bundleTarPath, - cwd: validateDir, - }); - - // Check for required OCI bundle files - const configJsonPath = join(validateDir, "config.json"); - const rootfsPath = join(validateDir, "rootfs"); - - // Verify config.json exists and is valid JSON - const configData = await readFile(configJsonPath, "utf8"); - const config = JSON.parse(configData); - - expect(config).toBeDefined(); - expect(config.ociVersion).toBeDefined(); - expect(config.process).toBeDefined(); - expect(config.root).toBeDefined(); - - // Verify rootfs directory exists - const rootfsStat = await import("fs/promises").then((fs) => - fs.stat(rootfsPath), - ); - expect(rootfsStat.isDirectory()).toBe(true); - - console.log("OCI bundle validation passed"); - } finally { - await rm(validateDir, { recursive: true, force: true }); - } -} - -beforeAll(async () => { - // Create test directory - await mkdir(TEST_DIR, { recursive: true }); - - // Check if Docker is available - try { - execSync("docker --version", { stdio: "pipe" }); - } catch (error) { - throw new Error( - "Docker is not available. Please install Docker to run OCI converter tests.", - ); - } - - // Check if skopeo is available - try { - execSync("skopeo --version", { stdio: "pipe" }); - } catch (error) { - throw new Error( - "skopeo is not available. Please install skopeo to run OCI converter tests.", - ); - } - - // Check if umoci is available - try { - execSync("umoci --version", { stdio: "pipe" }); - } catch (error) { - throw new Error( - "umoci is not available. Please install umoci to run OCI converter tests.", - ); - } -}); - -afterAll(async () => { - // Cleanup test directory - await rm(TEST_DIR, { recursive: true, force: true }); - - // Remove test Docker image - try { - execSync(`docker rmi ${TEST_IMAGE_NAME}`, { stdio: "pipe" }); - } catch (error) { - // Ignore errors when removing image - } -}); - -test("createTestDockerImage builds and saves Docker image", async () => { - const dockerTarPath = await createTestDockerImage(); - - // Verify the tar file was created - const stats = await import("fs/promises").then((fs) => - fs.stat(dockerTarPath), - ); - expect(stats.isFile()).toBe(true); - expect(stats.size).toBeGreaterThan(0); - - console.log( - `Test Docker image created: ${dockerTarPath} (${stats.size} bytes)`, - ); -}, 60000); - -test("convertDockerTarToOCIBundle converts Docker tar to OCI bundle", async () => { - const dockerTarPath = await createTestDockerImage(); - - const result = await convertDockerTarToOCIBundle(dockerTarPath); - - try { - // Verify the OCI bundle tar was created - const stats = await import("fs/promises").then((fs) => - fs.stat(result.bundleTarPath), - ); - expect(stats.isFile()).toBe(true); - expect(stats.size).toBeGreaterThan(0); - - console.log( - `OCI bundle created: ${result.bundleTarPath} (${stats.size} bytes)`, - ); - - // Validate the OCI bundle structure - await validateOCIBundle(result.bundleTarPath); - } finally { - await result.cleanup(); - } -}, 120000); - -test("full workflow: Docker image -> direct OCI bundle conversion", async () => { - // Create test Docker image - const dockerTarPath = await createTestDockerImage(); - - // Convert directly to OCI bundle (like the new simplified flow) - const convertResult = await convertDockerTarToOCIBundle(dockerTarPath); - - try { - // Verify the final OCI bundle - const stats = await import("fs/promises").then((fs) => - fs.stat(convertResult.bundleTarPath), - ); - expect(stats.isFile()).toBe(true); - expect(stats.size).toBeGreaterThan(0); - - // Validate OCI bundle structure - await validateOCIBundle(convertResult.bundleTarPath); - - console.log( - `Full workflow completed successfully: ${convertResult.bundleTarPath}`, - ); - } finally { - await convertResult.cleanup(); - } -}, 180000); diff --git a/cloud/packages/ci-manager/tests/rivet-e2e.test.ts b/cloud/packages/ci-manager/tests/rivet-e2e.test.ts deleted file mode 100644 index 29dbf914fc..0000000000 --- a/cloud/packages/ci-manager/tests/rivet-e2e.test.ts +++ /dev/null @@ -1,243 +0,0 @@ -import { execSync } from "child_process"; -import { RivetClient } from "@rivet-gg/api"; -import { mkdir, rm } from "fs/promises"; -import { afterAll, beforeAll, expect, test } from "vitest"; -import type { RivetUploadConfig } from "../src/rivet-uploader"; -import { - createActorFromBuild, - createTestWebServerContext, - pollBuildStatus, - testActorEndpoint, - waitForActorReady, -} from "./test-utils"; - -const TEST_DIR = "/tmp/rivet-test"; - -let rivetConfig: RivetUploadConfig; -const testActorIds: string[] = []; - -async function findCIManagerActor( - client: RivetClient, - projectId: string, -): Promise { - try { - const actorsResponse = await client.actors.list({ - project: projectId, - environment: "ci", - tagsJson: JSON.stringify({ name: "ci-manager" }), - }); - - const manager = actorsResponse.actors?.find( - (actor) => actor.tags?.name === "ci-manager", - ); - - return manager?.id || null; - } catch (error) { - console.error("Error finding CI manager actor:", error); - return null; - } -} - -async function createCIManagerActor( - client: RivetClient, - projectId: string, - token: string, -): Promise { - const { builds } = await client.builds.list({ - project: projectId, - environment: "ci", - tagsJson: JSON.stringify({ name: "ci-runner", current: "true" }), - }); - if (!builds[0]) throw new Error("Missing ci-runner build"); - - const createResponse = await client.actors.create({ - project: projectId, - environment: "ci", - body: { - tags: { - name: "ci-manager", - }, - buildTags: { - name: "ci-manager", - current: "true", - }, - runtime: { - environment: { - KANIKO_EXECUTION_MODE: "rivet", - KANIKO_BUILD_ID: builds[0].id, - RIVET_CLOUD_TOKEN: token, - RIVET_PROJECT: projectId, - RIVET_ENVIRONMENT: "ci", - }, - }, - network: { - ports: { - http: { protocol: "https", internalPort: 3000 }, - }, - waitReady: true, - }, - resources: { - cpu: 1000, - memory: 1024, - }, - lifecycle: { - killTimeout: 30000, - durable: true, - }, - }, - }); - - return createResponse.actor.id; -} - -async function destroyActor( - actorId: string, - config: RivetUploadConfig, -): Promise { - const client = new RivetClient({ token: config.token }); - - try { - await client.actors.destroy(actorId, { - project: config.project, - environment: config.environment, - }); - - console.log(`Actor destroyed: ${actorId}`); - } catch (error) { - throw new Error(`Failed to destroy actor: ${error}`); - } -} - -beforeAll(async () => { - await mkdir(TEST_DIR, { recursive: true }); - - const token = process.env.RIVET_CLOUD_TOKEN; - const project = process.env.RIVET_PROJECT; - const environment = process.env.RIVET_ENVIRONMENT; - - if (!token || !project || !environment) { - throw new Error( - "Missing required environment variables: RIVET_CLOUD_TOKEN, RIVET_PROJECT, RIVET_ENVIRONMENT", - ); - } - - rivetConfig = { token, project, environment }; - - try { - execSync("docker --version", { stdio: "pipe" }); - } catch (error) { - throw new Error( - "Docker is not available. Please install Docker to run Rivet tests.", - ); - } -}); - -afterAll(async () => { - for (const actorId of testActorIds) { - try { - await destroyActor(actorId, rivetConfig); - console.log(`Cleaned up test actor: ${actorId}`); - } catch (error) { - console.warn(`Failed to cleanup test actor ${actorId}:`, error); - } - } - - await rm(TEST_DIR, { recursive: true, force: true }); -}); - -test("full e2e", async () => { - const token = rivetConfig.token; - const projectId = rivetConfig.project; - const environmentName = rivetConfig.environment; - - const client = new RivetClient({ token }); - - let ciManagerActorId = await findCIManagerActor(client, projectId); - - if (!ciManagerActorId) { - console.log("Creating CI manager actor..."); - ciManagerActorId = await createCIManagerActor(client, projectId, token); - console.log(`Created CI manager actor: ${ciManagerActorId}`); - - await new Promise((resolve) => setTimeout(resolve, 10000)); - } else { - console.log(`Using existing CI manager actor: ${ciManagerActorId}`); - } - - const actorResponse = await client.actors.get(ciManagerActorId, { - project: projectId, - environment: "ci", - }); - - const endpoint = actorResponse.actor.network?.ports?.["http"]?.hostname; - if (!endpoint) { - throw new Error("Actor endpoint not available"); - } - - const serverUrl = `https://${endpoint}`; - console.log(`Using CI manager endpoint: ${serverUrl}`); - - const contextBuffer = await createTestWebServerContext(); - const buildName = "rivet-test-build"; - - const formData = new FormData(); - formData.append("buildName", buildName); - formData.append("dockerfilePath", "configs/build.dockerfile"); - formData.append("environmentId", rivetConfig.environment); - formData.append("context", new Blob([contextBuffer]), "context.tar.gz"); - - const response = await fetch( - `${serverUrl}/builds?serverUrl=${encodeURIComponent(serverUrl)}`, - { - method: "POST", - body: formData, - }, - ); - if (!response.ok) { - console.log( - "Response status", - response.statusText, - await response.text(), - ); - } - - expect(response.ok).toBe(true); - const result = await response.json(); - expect(result.buildId).toBeDefined(); - - const buildId = result.buildId; - console.log(`Started build: ${buildId}`); - - console.log("Polling build status..."); - const buildResult = await pollBuildStatus(serverUrl, buildId); - expect(buildResult.status).toBe("success"); - console.log(`Build completed with status: ${buildResult.status}`); - - console.log("Creating actor from build..."); - const actorResult = await createActorFromBuild( - buildResult.buildId, - buildName, - rivetConfig, - ); - - const actorId = actorResult.actorId; - testActorIds.push(actorId); - expect(actorResult.endpoint).toBeDefined(); - - console.log(`Actor created: ${actorId}`); - console.log(`Actor endpoint: ${actorResult.endpoint}`); - - await waitForActorReady(actorResult.endpoint); - - console.log("Testing actor HTTP endpoint..."); - const testResponse = await testActorEndpoint(actorResult.endpoint); - - expect(testResponse).toBeDefined(); - expect(testResponse.message).toBe("Rivet test successful!"); - expect(testResponse.timestamp).toBeDefined(); - expect(testResponse.hostname).toBeDefined(); - - console.log("Actor HTTP test successful:", response); - - console.log("✅ Full E2E test completed successfully"); -}, 600000); diff --git a/cloud/packages/ci-manager/tests/test-utils.ts b/cloud/packages/ci-manager/tests/test-utils.ts deleted file mode 100644 index 969e69b66a..0000000000 --- a/cloud/packages/ci-manager/tests/test-utils.ts +++ /dev/null @@ -1,361 +0,0 @@ -import { randomUUID } from "crypto"; -import { execSync } from "node:child_process"; -import { mkdir, readFile, writeFile } from "node:fs/promises"; -import { join } from "node:path"; -import * as tar from "tar"; - -export async function createFailingDockerContext(): Promise { - const tempDir = `/tmp/docker-context-fail-${Date.now()}-${Math.random().toString(36).substring(2)}`; - await mkdir(tempDir, { recursive: true }); - await mkdir(join(tempDir, "configs"), { recursive: true }); - - const dockerfile = ` -FROM alpine:latest -RUN exit 1 -CMD echo "This should never run" -`; - - await writeFile(join(tempDir, "configs/fail.dockerfile"), dockerfile); - - const tarPath = `/tmp/context-fail-${Date.now()}.tar.gz`; - - await tar.create( - { - gzip: true, - file: tarPath, - cwd: tempDir, - }, - ["."], - ); - - const fileBuffer = await readFile(tarPath); - return fileBuffer; -} - -export async function createTestWebServerImage(): Promise<{ - dockerTarPath: string; - imageName: string; -}> { - const testId = randomUUID(); - const imageName = `rivet-build:${testId}`; - const contextDir = `/tmp/webserver-context-${testId}`; - await mkdir(contextDir, { recursive: true }); - - const dockerfile = ` -FROM node:18-alpine -WORKDIR /app -COPY package.json server.js ./ -RUN npm install -EXPOSE 3000 -CMD ["node", "server.js"] -`; - - const packageJson = { - name: "test-webserver", - version: "1.0.0", - dependencies: { - express: "^4.18.0", - }, - }; - - const serverJs = ` -const express = require('express'); -const app = express(); -const port = 3000; - -app.get('/', (req, res) => { - res.json({ - message: 'Rivet test successful!', - timestamp: new Date().toISOString(), - hostname: require('os').hostname() - }); -}); - -app.get('/health', (req, res) => { - res.json({ status: 'healthy' }); -}); - -app.listen(port, '0.0.0.0', () => { - console.log(\`Test server listening on port \${port}\`); -}); -`; - - await mkdir(join(contextDir, "docker"), { recursive: true }); - await writeFile( - join(contextDir, "docker/app.dockerfile"), - dockerfile.trim(), - ); - await writeFile( - join(contextDir, "package.json"), - JSON.stringify(packageJson, null, 2), - ); - await writeFile(join(contextDir, "server.js"), serverJs.trim()); - - console.log(`Building test web server image: ${imageName}`); - execSync(`docker build -f docker/app.dockerfile -t ${imageName} .`, { - cwd: contextDir, - stdio: "pipe", - }); - - const dockerTarPath = `/tmp/webserver-image-${testId}.tar`; - console.log(`Saving Docker image to: ${dockerTarPath}`); - execSync(`docker save -o ${dockerTarPath} ${imageName}`, { - stdio: "pipe", - }); - - return { dockerTarPath, imageName }; -} - -export async function createTestWebServerContext(): Promise { - const testId = randomUUID(); - const tempDir = `/tmp/webserver-context-${testId}`; - await mkdir(tempDir, { recursive: true }); - await mkdir(join(tempDir, "configs"), { recursive: true }); - - const dockerfile = ` -FROM node:18-alpine -WORKDIR /app -COPY package.json server.js ./ -RUN npm install -EXPOSE 3000 -CMD ["node", "server.js"] -`; - - const packageJson = { - name: "test-webserver", - version: "1.0.0", - dependencies: { - express: "^4.18.0", - }, - }; - - const serverJs = ` -const express = require('express'); -const app = express(); -const port = 3000; - -app.get('/', (req, res) => { - res.json({ - message: 'Rivet test successful!', - timestamp: new Date().toISOString(), - hostname: require('os').hostname() - }); -}); - -app.get('/health', (req, res) => { - res.json({ status: 'healthy' }); -}); - -app.listen(port, '0.0.0.0', () => { - console.log(\`Test server listening on port \${port}\`); -}); -`; - - await writeFile( - join(tempDir, "configs/build.dockerfile"), - dockerfile.trim(), - ); - await writeFile( - join(tempDir, "package.json"), - JSON.stringify(packageJson, null, 2), - ); - await writeFile(join(tempDir, "server.js"), serverJs.trim()); - - const tarPath = `/tmp/webserver-context-${testId}.tar.gz`; - - await tar.create( - { - gzip: true, - file: tarPath, - cwd: tempDir, - }, - ["."], - ); - - const fileBuffer = await readFile(tarPath); - return fileBuffer; -} - -export async function downloadOutputTar( - serverUrl: string, - buildId: string, -): Promise { - const response = await fetch( - `${serverUrl}/builds/${buildId}/output.tar.gz`, - ); - - if (!response.ok) { - throw new Error(`Failed to download output: ${response.statusText}`); - } - - const arrayBuffer = await response.arrayBuffer(); - return Buffer.from(arrayBuffer); -} - -export async function pollBuildStatus( - baseUrl: string, - buildId?: string, -): Promise<{ status: string; buildId: string }> { - const maxAttempts = 150; - const interval = 2000; - - for (let attempt = 0; attempt < maxAttempts; attempt++) { - try { - const response = await fetch(`${baseUrl}/builds/${buildId}`); - if (!response.ok) { - throw new Error(`HTTP ${response.status}`); - } - - const build = await response.json(); - console.log( - `[${buildId}] Status: ${build.status.type} ${JSON.stringify(build.status.data)}`, - ); - - if ( - build.status.type === "success" || - build.status.type === "failure" - ) { - return { - status: build.status.type, - buildId: build.status.data?.buildId, - }; - } - - if (attempt < maxAttempts - 1) { - await new Promise((resolve) => setTimeout(resolve, interval)); - } - } catch (error) { - console.log( - `[${buildId}] Poll attempt ${attempt + 1} failed:`, - error, - ); - if (attempt < maxAttempts - 1) { - await new Promise((resolve) => setTimeout(resolve, interval)); - } - } - } - - throw new Error(`Build polling timeout after ${maxAttempts} attempts`); -} - -export async function createBuildWithContext( - baseUrl: string, - buildName: string, - dockerfilePath: string, - contextBuffer: Buffer, - environmentId?: string, -): Promise { - const formData = new FormData(); - formData.append("buildName", buildName); - formData.append("dockerfilePath", dockerfilePath); - if (environmentId) { - formData.append("environmentId", environmentId); - } - formData.append( - "context", - new Blob([contextBuffer], { type: "application/gzip" }), - ); - - const response = await fetch(`${baseUrl}/builds`, { - method: "POST", - body: formData, - }); - - if (!response.ok) { - throw new Error(`Failed to create build: ${response.statusText}`); - } - - const result = await response.json(); - return result.buildId; -} - -export async function getBuildStatus( - baseUrl: string, - buildId: string, -): Promise { - const response = await fetch(`${baseUrl}/builds/${buildId}`); - return await response.json(); -} - -export async function testActorEndpoint(endpoint: string): Promise { - const response = await fetch(`${endpoint}`, { - method: "GET", - headers: { "User-Agent": "rivet-test" }, - }); - - if (!response.ok) { - throw new Error(`HTTP ${response.status}: ${response.statusText}`); - } - - return await response.json(); -} - -export async function createActorFromBuild( - buildId: string, - buildName: string, - rivetConfig: { token: string; project: string; environment: string }, -): Promise<{ actorId: string; endpoint: string }> { - const { RivetClient } = await import("@rivet-gg/api"); - const client = new RivetClient({ token: rivetConfig.token }); - - console.log(`Creating actor with build ${buildName} and ID ${buildId}...`); - const { actor } = await client.actors.create({ - project: rivetConfig.project, - environment: rivetConfig.environment, - body: { - tags: { name: buildName }, - build: buildId, - network: { - ports: { - http: { - protocol: "https", - internalPort: 3000, - }, - }, - }, - resources: { - cpu: 100, - memory: 128, - }, - }, - }); - - const endpoint = actor.network?.ports?.http?.url; - if (!endpoint) { - throw new Error("Actor endpoint not available"); - } - - return { - actorId: actor.id, - endpoint, - }; -} - -export async function waitForActorReady(endpoint: string): Promise { - const maxAttempts = 30; - const interval = 2000; - - for (let attempt = 0; attempt < maxAttempts; attempt++) { - try { - const response = await fetch(`${endpoint}/health`, { - method: "GET", - headers: { "User-Agent": "rivet-test" }, - }); - - if (response.ok) { - console.log("Actor is ready!"); - return; - } - } catch (error) { - console.log( - `Waiting for actor to be ready... (attempt ${attempt + 1})`, - ); - } - - if (attempt < maxAttempts - 1) { - await new Promise((resolve) => setTimeout(resolve, interval)); - } - } - - throw new Error(`Actor not ready after ${maxAttempts} attempts`); -} diff --git a/cloud/packages/ci-manager/tests/upload-workflow.test.ts b/cloud/packages/ci-manager/tests/upload-workflow.test.ts deleted file mode 100644 index 8dafee4812..0000000000 --- a/cloud/packages/ci-manager/tests/upload-workflow.test.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { RivetClient } from "@rivet-gg/api"; -import { mkdir, rm } from "fs/promises"; -import { afterAll, beforeAll, expect, test } from "vitest"; -import { convertDockerTarToOCIBundle } from "../src/oci-converter"; -import { - type RivetUploadConfig, - uploadOCIBundleToRivet, -} from "../src/rivet-uploader"; -import { - createTestWebServerImage, - testActorEndpoint, - waitForActorReady, -} from "./test-utils"; - -const TEST_DIR = "/tmp/upload-test"; - -let rivetConfig: RivetUploadConfig; -const testActorIds: string[] = []; - -async function createRivetActor( - buildId: string, - buildName: string, - config: RivetUploadConfig, -): Promise<{ actorId: string; endpoint?: string }> { - const client = new RivetClient({ token: config.token }); - - try { - const response = await client.actors.create({ - project: config.project, - environment: config.environment, - body: { - tags: { name: buildName }, - buildTags: { - name: buildName, - current: "true", - }, - network: { - ports: { - http: { - protocol: "https", - internalPort: 3000, - }, - }, - }, - resources: { - cpu: 100, - memory: 128, - }, - }, - }); - - const actorId = response.actor.id; - - await new Promise((resolve) => setTimeout(resolve, 5000)); - - const actorDetails = await client.actors.get(actorId, { - project: config.project, - environment: config.environment, - }); - - const endpoint = actorDetails.actor.network?.ports?.http?.hostname; - - return { - actorId, - endpoint: endpoint ? `https://${endpoint}` : undefined, - }; - } catch (error) { - throw new Error(`Failed to create Rivet actor: ${error}`); - } -} - -async function destroyRivetActor( - actorId: string, - config: RivetUploadConfig, -): Promise { - const client = new RivetClient({ token: config.token }); - - try { - await client.actors.destroy(actorId, { - project: config.project, - environment: config.environment, - }); - - console.log(`Rivet actor destroyed: ${actorId}`); - } catch (error) { - throw new Error(`Failed to destroy Rivet actor: ${error}`); - } -} - -beforeAll(async () => { - await mkdir(TEST_DIR, { recursive: true }); - - const token = process.env.RIVET_CLOUD_TOKEN; - const project = process.env.RIVET_PROJECT; - const environment = process.env.RIVET_ENVIRONMENT; - - if (!token || !project || !environment) { - throw new Error( - "Missing required environment variables: RIVET_CLOUD_TOKEN, RIVET_PROJECT, RIVET_ENVIRONMENT", - ); - } - - rivetConfig = { token, project, environment: "staging" }; -}); - -afterAll(async () => { - for (const actorId of testActorIds) { - try { - await destroyRivetActor(actorId, rivetConfig); - console.log(`Cleaned up test actor: ${actorId}`); - } catch (error) { - console.warn(`Failed to cleanup test actor ${actorId}:`, error); - } - } - - await rm(TEST_DIR, { recursive: true, force: true }); -}); - -test("upload workflow", async () => { - const { dockerTarPath, imageName } = await createTestWebServerImage(); - const conversionResult = await convertDockerTarToOCIBundle(dockerTarPath); - - let actorId: string | undefined; - - try { - console.log("Uploading OCI bundle to Rivet..."); - const uploadResult = await uploadOCIBundleToRivet( - conversionResult.bundleTarPath, - "rivet-upload-test", - imageName, - rivetConfig, - "2.0.0", - ); - - console.log(`Build uploaded: ${uploadResult.buildId}`); - - console.log("Creating Rivet actor..."); - const actorResult = await createRivetActor( - uploadResult.buildId, - "rivet-upload-test", - rivetConfig, - ); - - actorId = actorResult.actorId; - testActorIds.push(actorId); - expect(actorResult.endpoint).toBeDefined(); - - console.log(`Actor created: ${actorId}`); - console.log(`Actor endpoint: ${actorResult.endpoint}`); - - await waitForActorReady(actorResult.endpoint!); - - console.log("Testing actor HTTP endpoint..."); - const response = await testActorEndpoint(actorResult.endpoint!); - - expect(response).toBeDefined(); - expect(response.message).toBe("Rivet test successful!"); - expect(response.timestamp).toBeDefined(); - expect(response.hostname).toBeDefined(); - - console.log("Actor HTTP test successful:", response); - - console.log("✅ Upload workflow test completed successfully"); - } finally { - await conversionResult.cleanup(); - } -}, 600000); diff --git a/cloud/packages/ci-manager/tsconfig.json b/cloud/packages/ci-manager/tsconfig.json deleted file mode 100644 index c593760ff0..0000000000 --- a/cloud/packages/ci-manager/tsconfig.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "module": "CommonJS", - "moduleResolution": "node", - "resolveJsonModule": true, - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "strict": true, - "noImplicitAny": true, - "strictNullChecks": true, - "strictFunctionTypes": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "noUncheckedIndexedAccess": true, - "skipLibCheck": true, - "declaration": false, - "outDir": "./dist", - "rootDir": "./src", - "removeComments": true, - "isolatedModules": true, - "allowJs": true, - "checkJs": false, - "incremental": true, - "tsBuildInfoFile": "./dist/.tsbuildinfo", - "types": ["node"], - "lib": ["ES2022", "DOM"] - }, - "include": ["src/**/*.ts"], - "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"], - "ts-node": { - "esm": true, - "experimentalSpecifierResolution": "node" - } -} diff --git a/cloud/packages/ci-manager/yarn.lock b/cloud/packages/ci-manager/yarn.lock deleted file mode 100644 index 2fba9a3a8d..0000000000 --- a/cloud/packages/ci-manager/yarn.lock +++ /dev/null @@ -1,2351 +0,0 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 8 - cacheKey: 10c0 - -"@esbuild/aix-ppc64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/aix-ppc64@npm:0.25.5" - conditions: os=aix & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/android-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/android-arm64@npm:0.25.5" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/android-arm@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/android-arm@npm:0.25.5" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - -"@esbuild/android-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/android-x64@npm:0.25.5" - conditions: os=android & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/darwin-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/darwin-arm64@npm:0.25.5" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/darwin-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/darwin-x64@npm:0.25.5" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/freebsd-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/freebsd-arm64@npm:0.25.5" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/freebsd-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/freebsd-x64@npm:0.25.5" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/linux-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-arm64@npm:0.25.5" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/linux-arm@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-arm@npm:0.25.5" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@esbuild/linux-ia32@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-ia32@npm:0.25.5" - conditions: os=linux & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/linux-loong64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-loong64@npm:0.25.5" - conditions: os=linux & cpu=loong64 - languageName: node - linkType: hard - -"@esbuild/linux-mips64el@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-mips64el@npm:0.25.5" - conditions: os=linux & cpu=mips64el - languageName: node - linkType: hard - -"@esbuild/linux-ppc64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-ppc64@npm:0.25.5" - conditions: os=linux & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/linux-riscv64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-riscv64@npm:0.25.5" - conditions: os=linux & cpu=riscv64 - languageName: node - linkType: hard - -"@esbuild/linux-s390x@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-s390x@npm:0.25.5" - conditions: os=linux & cpu=s390x - languageName: node - linkType: hard - -"@esbuild/linux-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-x64@npm:0.25.5" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/netbsd-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/netbsd-arm64@npm:0.25.5" - conditions: os=netbsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/netbsd-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/netbsd-x64@npm:0.25.5" - conditions: os=netbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/openbsd-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/openbsd-arm64@npm:0.25.5" - conditions: os=openbsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/openbsd-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/openbsd-x64@npm:0.25.5" - conditions: os=openbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/sunos-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/sunos-x64@npm:0.25.5" - conditions: os=sunos & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/win32-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/win32-arm64@npm:0.25.5" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/win32-ia32@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/win32-ia32@npm:0.25.5" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/win32-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/win32-x64@npm:0.25.5" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@hono/node-server@npm:^1.14.4": - version: 1.14.4 - resolution: "@hono/node-server@npm:1.14.4" - peerDependencies: - hono: ^4 - checksum: 10c0/1dc6296ddda0b9708cbafb406e22fb3d937505b80ec991483a5066ffa162da2cb2331b4591e7b4bbc07c62e2bea7b3a751cb0fcff33f9fba870ff95a694261ef - languageName: node - linkType: hard - -"@isaacs/cliui@npm:^8.0.2": - version: 8.0.2 - resolution: "@isaacs/cliui@npm:8.0.2" - dependencies: - string-width: "npm:^5.1.2" - string-width-cjs: "npm:string-width@^4.2.0" - strip-ansi: "npm:^7.0.1" - strip-ansi-cjs: "npm:strip-ansi@^6.0.1" - wrap-ansi: "npm:^8.1.0" - wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" - checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e - languageName: node - linkType: hard - -"@isaacs/fs-minipass@npm:^4.0.0": - version: 4.0.1 - resolution: "@isaacs/fs-minipass@npm:4.0.1" - dependencies: - minipass: "npm:^7.0.4" - checksum: 10c0/c25b6dc1598790d5b55c0947a9b7d111cfa92594db5296c3b907e2f533c033666f692a3939eadac17b1c7c40d362d0b0635dc874cbfe3e70db7c2b07cc97a5d2 - languageName: node - linkType: hard - -"@jridgewell/sourcemap-codec@npm:^1.5.0": - version: 1.5.0 - resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" - checksum: 10c0/2eb864f276eb1096c3c11da3e9bb518f6d9fc0023c78344cdc037abadc725172c70314bdb360f2d4b7bffec7f5d657ce006816bc5d4ecb35e61b66132db00c18 - languageName: node - linkType: hard - -"@npmcli/agent@npm:^3.0.0": - version: 3.0.0 - resolution: "@npmcli/agent@npm:3.0.0" - dependencies: - agent-base: "npm:^7.1.0" - http-proxy-agent: "npm:^7.0.0" - https-proxy-agent: "npm:^7.0.1" - lru-cache: "npm:^10.0.1" - socks-proxy-agent: "npm:^8.0.3" - checksum: 10c0/efe37b982f30740ee77696a80c196912c274ecd2cb243bc6ae7053a50c733ce0f6c09fda085145f33ecf453be19654acca74b69e81eaad4c90f00ccffe2f9271 - languageName: node - linkType: hard - -"@npmcli/fs@npm:^4.0.0": - version: 4.0.0 - resolution: "@npmcli/fs@npm:4.0.0" - dependencies: - semver: "npm:^7.3.5" - checksum: 10c0/c90935d5ce670c87b6b14fab04a965a3b8137e585f8b2a6257263bd7f97756dd736cb165bb470e5156a9e718ecd99413dccc54b1138c1a46d6ec7cf325982fe5 - languageName: node - linkType: hard - -"@pkgjs/parseargs@npm:^0.11.0": - version: 0.11.0 - resolution: "@pkgjs/parseargs@npm:0.11.0" - checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd - languageName: node - linkType: hard - -"@rivet-gg/api@npm:^25.4.2": - version: 25.4.2 - resolution: "@rivet-gg/api@npm:25.4.2" - dependencies: - form-data: "npm:^4.0.0" - js-base64: "npm:^3.7.5" - node-fetch: "npm:2" - qs: "npm:^6.11.2" - readable-stream: "npm:^4.5.2" - url-join: "npm:^5.0.0" - checksum: 10c0/eb6a25b1468b9cd8f9b548fa7cdec948d8bcc21bc1274b06507b1b519cbba739cc828974a0917ebee9ab18c92ba7fe228d8ac596b3e71c5efaf4f4f8ed12c8f1 - languageName: node - linkType: hard - -"@rollup/rollup-android-arm-eabi@npm:4.42.0": - version: 4.42.0 - resolution: "@rollup/rollup-android-arm-eabi@npm:4.42.0" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - -"@rollup/rollup-android-arm64@npm:4.42.0": - version: 4.42.0 - resolution: "@rollup/rollup-android-arm64@npm:4.42.0" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@rollup/rollup-darwin-arm64@npm:4.42.0": - version: 4.42.0 - resolution: "@rollup/rollup-darwin-arm64@npm:4.42.0" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@rollup/rollup-darwin-x64@npm:4.42.0": - version: 4.42.0 - resolution: "@rollup/rollup-darwin-x64@npm:4.42.0" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@rollup/rollup-freebsd-arm64@npm:4.42.0": - version: 4.42.0 - resolution: "@rollup/rollup-freebsd-arm64@npm:4.42.0" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - -"@rollup/rollup-freebsd-x64@npm:4.42.0": - version: 4.42.0 - resolution: "@rollup/rollup-freebsd-x64@npm:4.42.0" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@rollup/rollup-linux-arm-gnueabihf@npm:4.42.0": - version: 4.42.0 - resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.42.0" - conditions: os=linux & cpu=arm & libc=glibc - languageName: node - linkType: hard - -"@rollup/rollup-linux-arm-musleabihf@npm:4.42.0": - version: 4.42.0 - resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.42.0" - conditions: os=linux & cpu=arm & libc=musl - languageName: node - linkType: hard - -"@rollup/rollup-linux-arm64-gnu@npm:4.42.0": - version: 4.42.0 - resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.42.0" - conditions: os=linux & cpu=arm64 & libc=glibc - languageName: node - linkType: hard - -"@rollup/rollup-linux-arm64-musl@npm:4.42.0": - version: 4.42.0 - resolution: "@rollup/rollup-linux-arm64-musl@npm:4.42.0" - conditions: os=linux & cpu=arm64 & libc=musl - languageName: node - linkType: hard - -"@rollup/rollup-linux-loongarch64-gnu@npm:4.42.0": - version: 4.42.0 - resolution: "@rollup/rollup-linux-loongarch64-gnu@npm:4.42.0" - conditions: os=linux & cpu=loong64 & libc=glibc - languageName: node - linkType: hard - -"@rollup/rollup-linux-powerpc64le-gnu@npm:4.42.0": - version: 4.42.0 - resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.42.0" - conditions: os=linux & cpu=ppc64 & libc=glibc - languageName: node - linkType: hard - -"@rollup/rollup-linux-riscv64-gnu@npm:4.42.0": - version: 4.42.0 - resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.42.0" - conditions: os=linux & cpu=riscv64 & libc=glibc - languageName: node - linkType: hard - -"@rollup/rollup-linux-riscv64-musl@npm:4.42.0": - version: 4.42.0 - resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.42.0" - conditions: os=linux & cpu=riscv64 & libc=musl - languageName: node - linkType: hard - -"@rollup/rollup-linux-s390x-gnu@npm:4.42.0": - version: 4.42.0 - resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.42.0" - conditions: os=linux & cpu=s390x & libc=glibc - languageName: node - linkType: hard - -"@rollup/rollup-linux-x64-gnu@npm:4.42.0": - version: 4.42.0 - resolution: "@rollup/rollup-linux-x64-gnu@npm:4.42.0" - conditions: os=linux & cpu=x64 & libc=glibc - languageName: node - linkType: hard - -"@rollup/rollup-linux-x64-musl@npm:4.42.0": - version: 4.42.0 - resolution: "@rollup/rollup-linux-x64-musl@npm:4.42.0" - conditions: os=linux & cpu=x64 & libc=musl - languageName: node - linkType: hard - -"@rollup/rollup-win32-arm64-msvc@npm:4.42.0": - version: 4.42.0 - resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.42.0" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@rollup/rollup-win32-ia32-msvc@npm:4.42.0": - version: 4.42.0 - resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.42.0" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@rollup/rollup-win32-x64-msvc@npm:4.42.0": - version: 4.42.0 - resolution: "@rollup/rollup-win32-x64-msvc@npm:4.42.0" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@types/chai@npm:^5.2.2": - version: 5.2.2 - resolution: "@types/chai@npm:5.2.2" - dependencies: - "@types/deep-eql": "npm:*" - checksum: 10c0/49282bf0e8246800ebb36f17256f97bd3a8c4fb31f92ad3c0eaa7623518d7e87f1eaad4ad206960fcaf7175854bdff4cb167e4fe96811e0081b4ada83dd533ec - languageName: node - linkType: hard - -"@types/deep-eql@npm:*": - version: 4.0.2 - resolution: "@types/deep-eql@npm:4.0.2" - checksum: 10c0/bf3f811843117900d7084b9d0c852da9a044d12eb40e6de73b552598a6843c21291a8a381b0532644574beecd5e3491c5ff3a0365ab86b15d59862c025384844 - languageName: node - linkType: hard - -"@types/estree@npm:1.0.7": - version: 1.0.7 - resolution: "@types/estree@npm:1.0.7" - checksum: 10c0/be815254316882f7c40847336cd484c3bc1c3e34f710d197160d455dc9d6d050ffbf4c3bc76585dba86f737f020ab20bdb137ebe0e9116b0c86c7c0342221b8c - languageName: node - linkType: hard - -"@types/estree@npm:^1.0.0": - version: 1.0.8 - resolution: "@types/estree@npm:1.0.8" - checksum: 10c0/39d34d1afaa338ab9763f37ad6066e3f349444f9052b9676a7cc0252ef9485a41c6d81c9c4e0d26e9077993354edf25efc853f3224dd4b447175ef62bdcc86a5 - languageName: node - linkType: hard - -"@types/eventsource@npm:^1.1.15": - version: 1.1.15 - resolution: "@types/eventsource@npm:1.1.15" - checksum: 10c0/afee5c6c1185e365802349878411324569c77ae9878317b6e34bd633bdb5ee0a6eada6d1b358fec57640fe610eb43535344076db199895e1d9ab81511bb6ed0e - languageName: node - linkType: hard - -"@types/node@npm:^22.15.30": - version: 22.15.30 - resolution: "@types/node@npm:22.15.30" - dependencies: - undici-types: "npm:~6.21.0" - checksum: 10c0/ca330ac0e7fd502686d6df115fcc606aba46fd334220f749bbba2f639accdadcb23f7900603ceccdc8240be736739cad5c0b87c0fa92c9255a4dff245f07d664 - languageName: node - linkType: hard - -"@vitest/expect@npm:3.2.3": - version: 3.2.3 - resolution: "@vitest/expect@npm:3.2.3" - dependencies: - "@types/chai": "npm:^5.2.2" - "@vitest/spy": "npm:3.2.3" - "@vitest/utils": "npm:3.2.3" - chai: "npm:^5.2.0" - tinyrainbow: "npm:^2.0.0" - checksum: 10c0/5eb6278be8f5294779472d1276e150a1b573274441a68c2681c447179abd22af451813fdfbe87e04f5909ca7a0926700f9b79022f227c9816e5d0fa8e0229e15 - languageName: node - linkType: hard - -"@vitest/mocker@npm:3.2.3": - version: 3.2.3 - resolution: "@vitest/mocker@npm:3.2.3" - dependencies: - "@vitest/spy": "npm:3.2.3" - estree-walker: "npm:^3.0.3" - magic-string: "npm:^0.30.17" - peerDependencies: - msw: ^2.4.9 - vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 - peerDependenciesMeta: - msw: - optional: true - vite: - optional: true - checksum: 10c0/b670f229c3b1de5561de3cbbecb18f964d4888355d7f1cb8bbff4350b2cfbe477bef834cc2f66af7727ca7dc567540018885eb652f46e0be1cda4015491dc0a9 - languageName: node - linkType: hard - -"@vitest/pretty-format@npm:3.2.3, @vitest/pretty-format@npm:^3.2.3": - version: 3.2.3 - resolution: "@vitest/pretty-format@npm:3.2.3" - dependencies: - tinyrainbow: "npm:^2.0.0" - checksum: 10c0/e8fa7b97822c58404bef07d19fa9a49d5b7edb6797dd355584ad7246585bbbe9c55dd1fb05d0c3939b9c15fba05c3e134e2b96ea0cb64ca79a2b9dab60087a6a - languageName: node - linkType: hard - -"@vitest/runner@npm:3.2.3": - version: 3.2.3 - resolution: "@vitest/runner@npm:3.2.3" - dependencies: - "@vitest/utils": "npm:3.2.3" - pathe: "npm:^2.0.3" - strip-literal: "npm:^3.0.0" - checksum: 10c0/c20cb6e2ac4fdfb3d4f5136714ea65f9063562d3afaa1574dc82f53d061444bc01583f9915346768ca75f5ea0658f02fb594752e21abbca5ab50290f58732147 - languageName: node - linkType: hard - -"@vitest/snapshot@npm:3.2.3": - version: 3.2.3 - resolution: "@vitest/snapshot@npm:3.2.3" - dependencies: - "@vitest/pretty-format": "npm:3.2.3" - magic-string: "npm:^0.30.17" - pathe: "npm:^2.0.3" - checksum: 10c0/f6dd0248afb3f3cbcbbb9fd39c2c8273c4ec92176f65e6ba9d36a0c33552d3658013e3a02944e14c7637f51d6702a5c07963b59707ca459bd1ac31f39c81160c - languageName: node - linkType: hard - -"@vitest/spy@npm:3.2.3": - version: 3.2.3 - resolution: "@vitest/spy@npm:3.2.3" - dependencies: - tinyspy: "npm:^4.0.3" - checksum: 10c0/ce77d5934ac4741513993aad9d8ff44ff03ff5cf5a177e010c7ffcd8d3060087e56df1938c1100d49de712daf952cd2c72dd83e1684d043e698bd2afe0025f5e - languageName: node - linkType: hard - -"@vitest/utils@npm:3.2.3": - version: 3.2.3 - resolution: "@vitest/utils@npm:3.2.3" - dependencies: - "@vitest/pretty-format": "npm:3.2.3" - loupe: "npm:^3.1.3" - tinyrainbow: "npm:^2.0.0" - checksum: 10c0/c7a785a73bc0d7c0202ced0d9912639b9deb6f05dd6c25700a13d97e13320ccec57660f11ad1f9225419ac485339fdf7af28c8d77456bcb9558e6c7d73ad538a - languageName: node - linkType: hard - -"abbrev@npm:^3.0.0": - version: 3.0.1 - resolution: "abbrev@npm:3.0.1" - checksum: 10c0/21ba8f574ea57a3106d6d35623f2c4a9111d9ee3e9a5be47baed46ec2457d2eac46e07a5c4a60186f88cb98abbe3e24f2d4cca70bc2b12f1692523e2209a9ccf - languageName: node - linkType: hard - -"abort-controller@npm:^3.0.0": - version: 3.0.0 - resolution: "abort-controller@npm:3.0.0" - dependencies: - event-target-shim: "npm:^5.0.0" - checksum: 10c0/90ccc50f010250152509a344eb2e71977fbf8db0ab8f1061197e3275ddf6c61a41a6edfd7b9409c664513131dd96e962065415325ef23efa5db931b382d24ca5 - languageName: node - linkType: hard - -"agent-base@npm:^7.1.0, agent-base@npm:^7.1.2": - version: 7.1.3 - resolution: "agent-base@npm:7.1.3" - checksum: 10c0/6192b580c5b1d8fb399b9c62bf8343d76654c2dd62afcb9a52b2cf44a8b6ace1e3b704d3fe3547d91555c857d3df02603341ff2cb961b9cfe2b12f9f3c38ee11 - languageName: node - linkType: hard - -"ansi-regex@npm:^5.0.1": - version: 5.0.1 - resolution: "ansi-regex@npm:5.0.1" - checksum: 10c0/9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737 - languageName: node - linkType: hard - -"ansi-regex@npm:^6.0.1": - version: 6.1.0 - resolution: "ansi-regex@npm:6.1.0" - checksum: 10c0/a91daeddd54746338478eef88af3439a7edf30f8e23196e2d6ed182da9add559c601266dbef01c2efa46a958ad6f1f8b176799657616c702b5b02e799e7fd8dc - languageName: node - linkType: hard - -"ansi-styles@npm:^4.0.0": - version: 4.3.0 - resolution: "ansi-styles@npm:4.3.0" - dependencies: - color-convert: "npm:^2.0.1" - checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 - languageName: node - linkType: hard - -"ansi-styles@npm:^6.1.0": - version: 6.2.1 - resolution: "ansi-styles@npm:6.2.1" - checksum: 10c0/5d1ec38c123984bcedd996eac680d548f31828bd679a66db2bdf11844634dde55fec3efa9c6bb1d89056a5e79c1ac540c4c784d592ea1d25028a92227d2f2d5c - languageName: node - linkType: hard - -"assertion-error@npm:^2.0.1": - version: 2.0.1 - resolution: "assertion-error@npm:2.0.1" - checksum: 10c0/bbbcb117ac6480138f8c93cf7f535614282dea9dc828f540cdece85e3c665e8f78958b96afac52f29ff883c72638e6a87d469ecc9fe5bc902df03ed24a55dba8 - languageName: node - linkType: hard - -"asynckit@npm:^0.4.0": - version: 0.4.0 - resolution: "asynckit@npm:0.4.0" - checksum: 10c0/d73e2ddf20c4eb9337e1b3df1a0f6159481050a5de457c55b14ea2e5cb6d90bb69e004c9af54737a5ee0917fcf2c9e25de67777bbe58261847846066ba75bc9d - languageName: node - linkType: hard - -"balanced-match@npm:^1.0.0": - version: 1.0.2 - resolution: "balanced-match@npm:1.0.2" - checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee - languageName: node - linkType: hard - -"base64-js@npm:^1.3.1": - version: 1.5.1 - resolution: "base64-js@npm:1.5.1" - checksum: 10c0/f23823513b63173a001030fae4f2dabe283b99a9d324ade3ad3d148e218134676f1ee8568c877cd79ec1c53158dcf2d2ba527a97c606618928ba99dd930102bf - languageName: node - linkType: hard - -"brace-expansion@npm:^2.0.1": - version: 2.0.1 - resolution: "brace-expansion@npm:2.0.1" - dependencies: - balanced-match: "npm:^1.0.0" - checksum: 10c0/b358f2fe060e2d7a87aa015979ecea07f3c37d4018f8d6deb5bd4c229ad3a0384fe6029bb76cd8be63c81e516ee52d1a0673edbe2023d53a5191732ae3c3e49f - languageName: node - linkType: hard - -"buffer@npm:^6.0.3": - version: 6.0.3 - resolution: "buffer@npm:6.0.3" - dependencies: - base64-js: "npm:^1.3.1" - ieee754: "npm:^1.2.1" - checksum: 10c0/2a905fbbcde73cc5d8bd18d1caa23715d5f83a5935867c2329f0ac06104204ba7947be098fe1317fbd8830e26090ff8e764f08cd14fefc977bb248c3487bcbd0 - languageName: node - linkType: hard - -"cac@npm:^6.7.14": - version: 6.7.14 - resolution: "cac@npm:6.7.14" - checksum: 10c0/4ee06aaa7bab8981f0d54e5f5f9d4adcd64058e9697563ce336d8a3878ed018ee18ebe5359b2430eceae87e0758e62ea2019c3f52ae6e211b1bd2e133856cd10 - languageName: node - linkType: hard - -"cacache@npm:^19.0.1": - version: 19.0.1 - resolution: "cacache@npm:19.0.1" - dependencies: - "@npmcli/fs": "npm:^4.0.0" - fs-minipass: "npm:^3.0.0" - glob: "npm:^10.2.2" - lru-cache: "npm:^10.0.1" - minipass: "npm:^7.0.3" - minipass-collect: "npm:^2.0.1" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.4" - p-map: "npm:^7.0.2" - ssri: "npm:^12.0.0" - tar: "npm:^7.4.3" - unique-filename: "npm:^4.0.0" - checksum: 10c0/01f2134e1bd7d3ab68be851df96c8d63b492b1853b67f2eecb2c37bb682d37cb70bb858a16f2f0554d3c0071be6dfe21456a1ff6fa4b7eed996570d6a25ffe9c - languageName: node - linkType: hard - -"call-bind-apply-helpers@npm:^1.0.1, call-bind-apply-helpers@npm:^1.0.2": - version: 1.0.2 - resolution: "call-bind-apply-helpers@npm:1.0.2" - dependencies: - es-errors: "npm:^1.3.0" - function-bind: "npm:^1.1.2" - checksum: 10c0/47bd9901d57b857590431243fea704ff18078b16890a6b3e021e12d279bbf211d039155e27d7566b374d49ee1f8189344bac9833dec7a20cdec370506361c938 - languageName: node - linkType: hard - -"call-bound@npm:^1.0.2": - version: 1.0.4 - resolution: "call-bound@npm:1.0.4" - dependencies: - call-bind-apply-helpers: "npm:^1.0.2" - get-intrinsic: "npm:^1.3.0" - checksum: 10c0/f4796a6a0941e71c766aea672f63b72bc61234c4f4964dc6d7606e3664c307e7d77845328a8f3359ce39ddb377fed67318f9ee203dea1d47e46165dcf2917644 - languageName: node - linkType: hard - -"chai@npm:^5.2.0": - version: 5.2.0 - resolution: "chai@npm:5.2.0" - dependencies: - assertion-error: "npm:^2.0.1" - check-error: "npm:^2.1.1" - deep-eql: "npm:^5.0.1" - loupe: "npm:^3.1.0" - pathval: "npm:^2.0.0" - checksum: 10c0/dfd1cb719c7cebb051b727672d382a35338af1470065cb12adb01f4ee451bbf528e0e0f9ab2016af5fc1eea4df6e7f4504dc8443f8f00bd8fb87ad32dc516f7d - languageName: node - linkType: hard - -"check-error@npm:^2.1.1": - version: 2.1.1 - resolution: "check-error@npm:2.1.1" - checksum: 10c0/979f13eccab306cf1785fa10941a590b4e7ea9916ea2a4f8c87f0316fc3eab07eabefb6e587424ef0f88cbcd3805791f172ea739863ca3d7ce2afc54641c7f0e - languageName: node - linkType: hard - -"chownr@npm:^3.0.0": - version: 3.0.0 - resolution: "chownr@npm:3.0.0" - checksum: 10c0/43925b87700f7e3893296c8e9c56cc58f926411cce3a6e5898136daaf08f08b9a8eb76d37d3267e707d0dcc17aed2e2ebdf5848c0c3ce95cf910a919935c1b10 - languageName: node - linkType: hard - -"ci-manager@workspace:.": - version: 0.0.0-use.local - resolution: "ci-manager@workspace:." - dependencies: - "@hono/node-server": "npm:^1.14.4" - "@rivet-gg/api": "npm:^25.4.2" - "@types/eventsource": "npm:^1.1.15" - "@types/node": "npm:^22.15.30" - eventsource: "npm:^4.0.0" - get-port: "npm:^7.1.0" - hono: "npm:^4.7.11" - nanoevents: "npm:^9.1.0" - tar: "npm:^7.4.3" - tsx: "npm:^4.19.4" - typescript: "npm:^5.7.2" - vitest: "npm:^3.2.2" - zod: "npm:^3.25.56" - zx: "npm:^8.1.9" - peerDependencies: - typescript: ^5 - languageName: unknown - linkType: soft - -"color-convert@npm:^2.0.1": - version: 2.0.1 - resolution: "color-convert@npm:2.0.1" - dependencies: - color-name: "npm:~1.1.4" - checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 - languageName: node - linkType: hard - -"color-name@npm:~1.1.4": - version: 1.1.4 - resolution: "color-name@npm:1.1.4" - checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 - languageName: node - linkType: hard - -"combined-stream@npm:^1.0.8": - version: 1.0.8 - resolution: "combined-stream@npm:1.0.8" - dependencies: - delayed-stream: "npm:~1.0.0" - checksum: 10c0/0dbb829577e1b1e839fa82b40c07ffaf7de8a09b935cadd355a73652ae70a88b4320db322f6634a4ad93424292fa80973ac6480986247f1734a1137debf271d5 - languageName: node - linkType: hard - -"cross-spawn@npm:^7.0.6": - version: 7.0.6 - resolution: "cross-spawn@npm:7.0.6" - dependencies: - path-key: "npm:^3.1.0" - shebang-command: "npm:^2.0.0" - which: "npm:^2.0.1" - checksum: 10c0/053ea8b2135caff68a9e81470e845613e374e7309a47731e81639de3eaeb90c3d01af0e0b44d2ab9d50b43467223b88567dfeb3262db942dc063b9976718ffc1 - languageName: node - linkType: hard - -"debug@npm:4, debug@npm:^4.3.4, debug@npm:^4.4.1": - version: 4.4.1 - resolution: "debug@npm:4.4.1" - dependencies: - ms: "npm:^2.1.3" - peerDependenciesMeta: - supports-color: - optional: true - checksum: 10c0/d2b44bc1afd912b49bb7ebb0d50a860dc93a4dd7d946e8de94abc957bb63726b7dd5aa48c18c2386c379ec024c46692e15ed3ed97d481729f929201e671fcd55 - languageName: node - linkType: hard - -"deep-eql@npm:^5.0.1": - version: 5.0.2 - resolution: "deep-eql@npm:5.0.2" - checksum: 10c0/7102cf3b7bb719c6b9c0db2e19bf0aa9318d141581befe8c7ce8ccd39af9eaa4346e5e05adef7f9bd7015da0f13a3a25dcfe306ef79dc8668aedbecb658dd247 - languageName: node - linkType: hard - -"delayed-stream@npm:~1.0.0": - version: 1.0.0 - resolution: "delayed-stream@npm:1.0.0" - checksum: 10c0/d758899da03392e6712f042bec80aa293bbe9e9ff1b2634baae6a360113e708b91326594c8a486d475c69d6259afb7efacdc3537bfcda1c6c648e390ce601b19 - languageName: node - linkType: hard - -"dunder-proto@npm:^1.0.1": - version: 1.0.1 - resolution: "dunder-proto@npm:1.0.1" - dependencies: - call-bind-apply-helpers: "npm:^1.0.1" - es-errors: "npm:^1.3.0" - gopd: "npm:^1.2.0" - checksum: 10c0/199f2a0c1c16593ca0a145dbf76a962f8033ce3129f01284d48c45ed4e14fea9bbacd7b3610b6cdc33486cef20385ac054948fefc6272fcce645c09468f93031 - languageName: node - linkType: hard - -"eastasianwidth@npm:^0.2.0": - version: 0.2.0 - resolution: "eastasianwidth@npm:0.2.0" - checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 - languageName: node - linkType: hard - -"emoji-regex@npm:^8.0.0": - version: 8.0.0 - resolution: "emoji-regex@npm:8.0.0" - checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 - languageName: node - linkType: hard - -"emoji-regex@npm:^9.2.2": - version: 9.2.2 - resolution: "emoji-regex@npm:9.2.2" - checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 - languageName: node - linkType: hard - -"encoding@npm:^0.1.13": - version: 0.1.13 - resolution: "encoding@npm:0.1.13" - dependencies: - iconv-lite: "npm:^0.6.2" - checksum: 10c0/36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039 - languageName: node - linkType: hard - -"env-paths@npm:^2.2.0": - version: 2.2.1 - resolution: "env-paths@npm:2.2.1" - checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 - languageName: node - linkType: hard - -"err-code@npm:^2.0.2": - version: 2.0.3 - resolution: "err-code@npm:2.0.3" - checksum: 10c0/b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66 - languageName: node - linkType: hard - -"es-define-property@npm:^1.0.1": - version: 1.0.1 - resolution: "es-define-property@npm:1.0.1" - checksum: 10c0/3f54eb49c16c18707949ff25a1456728c883e81259f045003499efba399c08bad00deebf65cccde8c0e07908c1a225c9d472b7107e558f2a48e28d530e34527c - languageName: node - linkType: hard - -"es-errors@npm:^1.3.0": - version: 1.3.0 - resolution: "es-errors@npm:1.3.0" - checksum: 10c0/0a61325670072f98d8ae3b914edab3559b6caa980f08054a3b872052640d91da01d38df55df797fcc916389d77fc92b8d5906cf028f4db46d7e3003abecbca85 - languageName: node - linkType: hard - -"es-module-lexer@npm:^1.7.0": - version: 1.7.0 - resolution: "es-module-lexer@npm:1.7.0" - checksum: 10c0/4c935affcbfeba7fb4533e1da10fa8568043df1e3574b869385980de9e2d475ddc36769891936dbb07036edb3c3786a8b78ccf44964cd130dedc1f2c984b6c7b - languageName: node - linkType: hard - -"es-object-atoms@npm:^1.0.0, es-object-atoms@npm:^1.1.1": - version: 1.1.1 - resolution: "es-object-atoms@npm:1.1.1" - dependencies: - es-errors: "npm:^1.3.0" - checksum: 10c0/65364812ca4daf48eb76e2a3b7a89b3f6a2e62a1c420766ce9f692665a29d94fe41fe88b65f24106f449859549711e4b40d9fb8002d862dfd7eb1c512d10be0c - languageName: node - linkType: hard - -"es-set-tostringtag@npm:^2.1.0": - version: 2.1.0 - resolution: "es-set-tostringtag@npm:2.1.0" - dependencies: - es-errors: "npm:^1.3.0" - get-intrinsic: "npm:^1.2.6" - has-tostringtag: "npm:^1.0.2" - hasown: "npm:^2.0.2" - checksum: 10c0/ef2ca9ce49afe3931cb32e35da4dcb6d86ab02592cfc2ce3e49ced199d9d0bb5085fc7e73e06312213765f5efa47cc1df553a6a5154584b21448e9fb8355b1af - languageName: node - linkType: hard - -"esbuild@npm:^0.25.0, esbuild@npm:~0.25.0": - version: 0.25.5 - resolution: "esbuild@npm:0.25.5" - dependencies: - "@esbuild/aix-ppc64": "npm:0.25.5" - "@esbuild/android-arm": "npm:0.25.5" - "@esbuild/android-arm64": "npm:0.25.5" - "@esbuild/android-x64": "npm:0.25.5" - "@esbuild/darwin-arm64": "npm:0.25.5" - "@esbuild/darwin-x64": "npm:0.25.5" - "@esbuild/freebsd-arm64": "npm:0.25.5" - "@esbuild/freebsd-x64": "npm:0.25.5" - "@esbuild/linux-arm": "npm:0.25.5" - "@esbuild/linux-arm64": "npm:0.25.5" - "@esbuild/linux-ia32": "npm:0.25.5" - "@esbuild/linux-loong64": "npm:0.25.5" - "@esbuild/linux-mips64el": "npm:0.25.5" - "@esbuild/linux-ppc64": "npm:0.25.5" - "@esbuild/linux-riscv64": "npm:0.25.5" - "@esbuild/linux-s390x": "npm:0.25.5" - "@esbuild/linux-x64": "npm:0.25.5" - "@esbuild/netbsd-arm64": "npm:0.25.5" - "@esbuild/netbsd-x64": "npm:0.25.5" - "@esbuild/openbsd-arm64": "npm:0.25.5" - "@esbuild/openbsd-x64": "npm:0.25.5" - "@esbuild/sunos-x64": "npm:0.25.5" - "@esbuild/win32-arm64": "npm:0.25.5" - "@esbuild/win32-ia32": "npm:0.25.5" - "@esbuild/win32-x64": "npm:0.25.5" - dependenciesMeta: - "@esbuild/aix-ppc64": - optional: true - "@esbuild/android-arm": - optional: true - "@esbuild/android-arm64": - optional: true - "@esbuild/android-x64": - optional: true - "@esbuild/darwin-arm64": - optional: true - "@esbuild/darwin-x64": - optional: true - "@esbuild/freebsd-arm64": - optional: true - "@esbuild/freebsd-x64": - optional: true - "@esbuild/linux-arm": - optional: true - "@esbuild/linux-arm64": - optional: true - "@esbuild/linux-ia32": - optional: true - "@esbuild/linux-loong64": - optional: true - "@esbuild/linux-mips64el": - optional: true - "@esbuild/linux-ppc64": - optional: true - "@esbuild/linux-riscv64": - optional: true - "@esbuild/linux-s390x": - optional: true - "@esbuild/linux-x64": - optional: true - "@esbuild/netbsd-arm64": - optional: true - "@esbuild/netbsd-x64": - optional: true - "@esbuild/openbsd-arm64": - optional: true - "@esbuild/openbsd-x64": - optional: true - "@esbuild/sunos-x64": - optional: true - "@esbuild/win32-arm64": - optional: true - "@esbuild/win32-ia32": - optional: true - "@esbuild/win32-x64": - optional: true - bin: - esbuild: bin/esbuild - checksum: 10c0/aba8cbc11927fa77562722ed5e95541ce2853f67ad7bdc40382b558abc2e0ec57d92ffb820f082ba2047b4ef9f3bc3da068cdebe30dfd3850cfa3827a78d604e - languageName: node - linkType: hard - -"estree-walker@npm:^3.0.3": - version: 3.0.3 - resolution: "estree-walker@npm:3.0.3" - dependencies: - "@types/estree": "npm:^1.0.0" - checksum: 10c0/c12e3c2b2642d2bcae7d5aa495c60fa2f299160946535763969a1c83fc74518ffa9c2cd3a8b69ac56aea547df6a8aac25f729a342992ef0bbac5f1c73e78995d - languageName: node - linkType: hard - -"event-target-shim@npm:^5.0.0": - version: 5.0.1 - resolution: "event-target-shim@npm:5.0.1" - checksum: 10c0/0255d9f936215fd206156fd4caa9e8d35e62075d720dc7d847e89b417e5e62cf1ce6c9b4e0a1633a9256de0efefaf9f8d26924b1f3c8620cffb9db78e7d3076b - languageName: node - linkType: hard - -"events@npm:^3.3.0": - version: 3.3.0 - resolution: "events@npm:3.3.0" - checksum: 10c0/d6b6f2adbccbcda74ddbab52ed07db727ef52e31a61ed26db9feb7dc62af7fc8e060defa65e5f8af9449b86b52cc1a1f6a79f2eafcf4e62add2b7a1fa4a432f6 - languageName: node - linkType: hard - -"eventsource-parser@npm:^3.0.1": - version: 3.0.2 - resolution: "eventsource-parser@npm:3.0.2" - checksum: 10c0/067c6e60b7c68a4577630cc7e11d2aaeef52005e377a213308c7c2350596a175d5a179671d85f570726dce3f451c15d174ece4479ce68a1805686c88950d08dd - languageName: node - linkType: hard - -"eventsource@npm:^4.0.0": - version: 4.0.0 - resolution: "eventsource@npm:4.0.0" - dependencies: - eventsource-parser: "npm:^3.0.1" - checksum: 10c0/908a3f64b60aadd053b9fd8ea8b6a896a4faf32dbbaf0150e91abbec179a9e2a3da261fb577ae296df8b744de91962d69a60b10e8d7092d7802e6e3e7a8b0f0e - languageName: node - linkType: hard - -"expect-type@npm:^1.2.1": - version: 1.2.1 - resolution: "expect-type@npm:1.2.1" - checksum: 10c0/b775c9adab3c190dd0d398c722531726cdd6022849b4adba19dceab58dda7e000a7c6c872408cd73d665baa20d381eca36af4f7b393a4ba60dd10232d1fb8898 - languageName: node - linkType: hard - -"exponential-backoff@npm:^3.1.1": - version: 3.1.2 - resolution: "exponential-backoff@npm:3.1.2" - checksum: 10c0/d9d3e1eafa21b78464297df91f1776f7fbaa3d5e3f7f0995648ca5b89c069d17055033817348d9f4a43d1c20b0eab84f75af6991751e839df53e4dfd6f22e844 - languageName: node - linkType: hard - -"fdir@npm:^6.4.4": - version: 6.4.5 - resolution: "fdir@npm:6.4.5" - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - checksum: 10c0/5d63330a1b97165e9b0fb20369fafc7cf826bc4b3e374efcb650bc77d7145ac01193b5da1a7591eab89ae6fd6b15cdd414085910b2a2b42296b1480c9f2677af - languageName: node - linkType: hard - -"foreground-child@npm:^3.1.0": - version: 3.3.1 - resolution: "foreground-child@npm:3.3.1" - dependencies: - cross-spawn: "npm:^7.0.6" - signal-exit: "npm:^4.0.1" - checksum: 10c0/8986e4af2430896e65bc2788d6679067294d6aee9545daefc84923a0a4b399ad9c7a3ea7bd8c0b2b80fdf4a92de4c69df3f628233ff3224260e9c1541a9e9ed3 - languageName: node - linkType: hard - -"form-data@npm:^4.0.0": - version: 4.0.3 - resolution: "form-data@npm:4.0.3" - dependencies: - asynckit: "npm:^0.4.0" - combined-stream: "npm:^1.0.8" - es-set-tostringtag: "npm:^2.1.0" - hasown: "npm:^2.0.2" - mime-types: "npm:^2.1.12" - checksum: 10c0/f0cf45873d600110b5fadf5804478377694f73a1ed97aaa370a74c90cebd7fe6e845a081171668a5476477d0d55a73a4e03d6682968fa8661eac2a81d651fcdb - languageName: node - linkType: hard - -"fs-minipass@npm:^3.0.0": - version: 3.0.3 - resolution: "fs-minipass@npm:3.0.3" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94 - languageName: node - linkType: hard - -"fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": - version: 2.3.3 - resolution: "fsevents@npm:2.3.3" - dependencies: - node-gyp: "npm:latest" - checksum: 10c0/a1f0c44595123ed717febbc478aa952e47adfc28e2092be66b8ab1635147254ca6cfe1df792a8997f22716d4cbafc73309899ff7bfac2ac3ad8cf2e4ecc3ec60 - conditions: os=darwin - languageName: node - linkType: hard - -"fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": - version: 2.3.3 - resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" - dependencies: - node-gyp: "npm:latest" - conditions: os=darwin - languageName: node - linkType: hard - -"function-bind@npm:^1.1.2": - version: 1.1.2 - resolution: "function-bind@npm:1.1.2" - checksum: 10c0/d8680ee1e5fcd4c197e4ac33b2b4dce03c71f4d91717292785703db200f5c21f977c568d28061226f9b5900cbcd2c84463646134fd5337e7925e0942bc3f46d5 - languageName: node - linkType: hard - -"get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.3.0": - version: 1.3.0 - resolution: "get-intrinsic@npm:1.3.0" - dependencies: - call-bind-apply-helpers: "npm:^1.0.2" - es-define-property: "npm:^1.0.1" - es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.1.1" - function-bind: "npm:^1.1.2" - get-proto: "npm:^1.0.1" - gopd: "npm:^1.2.0" - has-symbols: "npm:^1.1.0" - hasown: "npm:^2.0.2" - math-intrinsics: "npm:^1.1.0" - checksum: 10c0/52c81808af9a8130f581e6a6a83e1ba4a9f703359e7a438d1369a5267a25412322f03dcbd7c549edaef0b6214a0630a28511d7df0130c93cfd380f4fa0b5b66a - languageName: node - linkType: hard - -"get-port@npm:^7.1.0": - version: 7.1.0 - resolution: "get-port@npm:7.1.0" - checksum: 10c0/896051fea0fd3df58c050566754ab91f46406e898ce0c708414739d908a5ac03ffef3eca7a494ea9cc1914439e8caccd2218010d1eeabdde914b9ff920fa28fc - languageName: node - linkType: hard - -"get-proto@npm:^1.0.1": - version: 1.0.1 - resolution: "get-proto@npm:1.0.1" - dependencies: - dunder-proto: "npm:^1.0.1" - es-object-atoms: "npm:^1.0.0" - checksum: 10c0/9224acb44603c5526955e83510b9da41baf6ae73f7398875fba50edc5e944223a89c4a72b070fcd78beb5f7bdda58ecb6294adc28f7acfc0da05f76a2399643c - languageName: node - linkType: hard - -"get-tsconfig@npm:^4.7.5": - version: 4.10.1 - resolution: "get-tsconfig@npm:4.10.1" - dependencies: - resolve-pkg-maps: "npm:^1.0.0" - checksum: 10c0/7f8e3dabc6a49b747920a800fb88e1952fef871cdf51b79e98db48275a5de6cdaf499c55ee67df5fa6fe7ce65f0063e26de0f2e53049b408c585aa74d39ffa21 - languageName: node - linkType: hard - -"glob@npm:^10.2.2": - version: 10.4.5 - resolution: "glob@npm:10.4.5" - dependencies: - foreground-child: "npm:^3.1.0" - jackspeak: "npm:^3.1.2" - minimatch: "npm:^9.0.4" - minipass: "npm:^7.1.2" - package-json-from-dist: "npm:^1.0.0" - path-scurry: "npm:^1.11.1" - bin: - glob: dist/esm/bin.mjs - checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e - languageName: node - linkType: hard - -"gopd@npm:^1.2.0": - version: 1.2.0 - resolution: "gopd@npm:1.2.0" - checksum: 10c0/50fff1e04ba2b7737c097358534eacadad1e68d24cccee3272e04e007bed008e68d2614f3987788428fd192a5ae3889d08fb2331417e4fc4a9ab366b2043cead - languageName: node - linkType: hard - -"graceful-fs@npm:^4.2.6": - version: 4.2.11 - resolution: "graceful-fs@npm:4.2.11" - checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 - languageName: node - linkType: hard - -"has-symbols@npm:^1.0.3, has-symbols@npm:^1.1.0": - version: 1.1.0 - resolution: "has-symbols@npm:1.1.0" - checksum: 10c0/dde0a734b17ae51e84b10986e651c664379018d10b91b6b0e9b293eddb32f0f069688c841fb40f19e9611546130153e0a2a48fd7f512891fb000ddfa36f5a20e - languageName: node - linkType: hard - -"has-tostringtag@npm:^1.0.2": - version: 1.0.2 - resolution: "has-tostringtag@npm:1.0.2" - dependencies: - has-symbols: "npm:^1.0.3" - checksum: 10c0/a8b166462192bafe3d9b6e420a1d581d93dd867adb61be223a17a8d6dad147aa77a8be32c961bb2f27b3ef893cae8d36f564ab651f5e9b7938ae86f74027c48c - languageName: node - linkType: hard - -"hasown@npm:^2.0.2": - version: 2.0.2 - resolution: "hasown@npm:2.0.2" - dependencies: - function-bind: "npm:^1.1.2" - checksum: 10c0/3769d434703b8ac66b209a4cca0737519925bbdb61dd887f93a16372b14694c63ff4e797686d87c90f08168e81082248b9b028bad60d4da9e0d1148766f56eb9 - languageName: node - linkType: hard - -"hono@npm:^4.7.11": - version: 4.7.11 - resolution: "hono@npm:4.7.11" - checksum: 10c0/2821471b09f2e9f7bab5ad7412e2e44df5f07b7098508d70dd6e368b933580f03a06c30e20dd764b53e0121e1b1ff2132ae98cffa7fd1b286e299f9054effd6a - languageName: node - linkType: hard - -"http-cache-semantics@npm:^4.1.1": - version: 4.2.0 - resolution: "http-cache-semantics@npm:4.2.0" - checksum: 10c0/45b66a945cf13ec2d1f29432277201313babf4a01d9e52f44b31ca923434083afeca03f18417f599c9ab3d0e7b618ceb21257542338b57c54b710463b4a53e37 - languageName: node - linkType: hard - -"http-proxy-agent@npm:^7.0.0": - version: 7.0.2 - resolution: "http-proxy-agent@npm:7.0.2" - dependencies: - agent-base: "npm:^7.1.0" - debug: "npm:^4.3.4" - checksum: 10c0/4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921 - languageName: node - linkType: hard - -"https-proxy-agent@npm:^7.0.1": - version: 7.0.6 - resolution: "https-proxy-agent@npm:7.0.6" - dependencies: - agent-base: "npm:^7.1.2" - debug: "npm:4" - checksum: 10c0/f729219bc735edb621fa30e6e84e60ee5d00802b8247aac0d7b79b0bd6d4b3294737a337b93b86a0bd9e68099d031858a39260c976dc14cdbba238ba1f8779ac - languageName: node - linkType: hard - -"iconv-lite@npm:^0.6.2": - version: 0.6.3 - resolution: "iconv-lite@npm:0.6.3" - dependencies: - safer-buffer: "npm:>= 2.1.2 < 3.0.0" - checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 - languageName: node - linkType: hard - -"ieee754@npm:^1.2.1": - version: 1.2.1 - resolution: "ieee754@npm:1.2.1" - checksum: 10c0/b0782ef5e0935b9f12883a2e2aa37baa75da6e66ce6515c168697b42160807d9330de9a32ec1ed73149aea02e0d822e572bca6f1e22bdcbd2149e13b050b17bb - languageName: node - linkType: hard - -"imurmurhash@npm:^0.1.4": - version: 0.1.4 - resolution: "imurmurhash@npm:0.1.4" - checksum: 10c0/8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 - languageName: node - linkType: hard - -"ip-address@npm:^9.0.5": - version: 9.0.5 - resolution: "ip-address@npm:9.0.5" - dependencies: - jsbn: "npm:1.1.0" - sprintf-js: "npm:^1.1.3" - checksum: 10c0/331cd07fafcb3b24100613e4b53e1a2b4feab11e671e655d46dc09ee233da5011284d09ca40c4ecbdfe1d0004f462958675c224a804259f2f78d2465a87824bc - languageName: node - linkType: hard - -"is-fullwidth-code-point@npm:^3.0.0": - version: 3.0.0 - resolution: "is-fullwidth-code-point@npm:3.0.0" - checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc - languageName: node - linkType: hard - -"isexe@npm:^2.0.0": - version: 2.0.0 - resolution: "isexe@npm:2.0.0" - checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d - languageName: node - linkType: hard - -"isexe@npm:^3.1.1": - version: 3.1.1 - resolution: "isexe@npm:3.1.1" - checksum: 10c0/9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7 - languageName: node - linkType: hard - -"jackspeak@npm:^3.1.2": - version: 3.4.3 - resolution: "jackspeak@npm:3.4.3" - dependencies: - "@isaacs/cliui": "npm:^8.0.2" - "@pkgjs/parseargs": "npm:^0.11.0" - dependenciesMeta: - "@pkgjs/parseargs": - optional: true - checksum: 10c0/6acc10d139eaefdbe04d2f679e6191b3abf073f111edf10b1de5302c97ec93fffeb2fdd8681ed17f16268aa9dd4f8c588ed9d1d3bffbbfa6e8bf897cbb3149b9 - languageName: node - linkType: hard - -"js-base64@npm:^3.7.5": - version: 3.7.7 - resolution: "js-base64@npm:3.7.7" - checksum: 10c0/3c905a7e78b601e4751b5e710edd0d6d045ce2d23eb84c9df03515371e1b291edc72808dc91e081cb9855aef6758292a2407006f4608ec3705373dd8baf2f80f - languageName: node - linkType: hard - -"js-tokens@npm:^9.0.1": - version: 9.0.1 - resolution: "js-tokens@npm:9.0.1" - checksum: 10c0/68dcab8f233dde211a6b5fd98079783cbcd04b53617c1250e3553ee16ab3e6134f5e65478e41d82f6d351a052a63d71024553933808570f04dbf828d7921e80e - languageName: node - linkType: hard - -"jsbn@npm:1.1.0": - version: 1.1.0 - resolution: "jsbn@npm:1.1.0" - checksum: 10c0/4f907fb78d7b712e11dea8c165fe0921f81a657d3443dde75359ed52eb2b5d33ce6773d97985a089f09a65edd80b11cb75c767b57ba47391fee4c969f7215c96 - languageName: node - linkType: hard - -"loupe@npm:^3.1.0, loupe@npm:^3.1.3": - version: 3.1.3 - resolution: "loupe@npm:3.1.3" - checksum: 10c0/f5dab4144254677de83a35285be1b8aba58b3861439ce4ba65875d0d5f3445a4a496daef63100ccf02b2dbc25bf58c6db84c9cb0b96d6435331e9d0a33b48541 - languageName: node - linkType: hard - -"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": - version: 10.4.3 - resolution: "lru-cache@npm:10.4.3" - checksum: 10c0/ebd04fbca961e6c1d6c0af3799adcc966a1babe798f685bb84e6599266599cd95d94630b10262f5424539bc4640107e8a33aa28585374abf561d30d16f4b39fb - languageName: node - linkType: hard - -"magic-string@npm:^0.30.17": - version: 0.30.17 - resolution: "magic-string@npm:0.30.17" - dependencies: - "@jridgewell/sourcemap-codec": "npm:^1.5.0" - checksum: 10c0/16826e415d04b88378f200fe022b53e638e3838b9e496edda6c0e086d7753a44a6ed187adc72d19f3623810589bf139af1a315541cd6a26ae0771a0193eaf7b8 - languageName: node - linkType: hard - -"make-fetch-happen@npm:^14.0.3": - version: 14.0.3 - resolution: "make-fetch-happen@npm:14.0.3" - dependencies: - "@npmcli/agent": "npm:^3.0.0" - cacache: "npm:^19.0.1" - http-cache-semantics: "npm:^4.1.1" - minipass: "npm:^7.0.2" - minipass-fetch: "npm:^4.0.0" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.4" - negotiator: "npm:^1.0.0" - proc-log: "npm:^5.0.0" - promise-retry: "npm:^2.0.1" - ssri: "npm:^12.0.0" - checksum: 10c0/c40efb5e5296e7feb8e37155bde8eb70bc57d731b1f7d90e35a092fde403d7697c56fb49334d92d330d6f1ca29a98142036d6480a12681133a0a1453164cb2f0 - languageName: node - linkType: hard - -"math-intrinsics@npm:^1.1.0": - version: 1.1.0 - resolution: "math-intrinsics@npm:1.1.0" - checksum: 10c0/7579ff94e899e2f76ab64491d76cf606274c874d8f2af4a442c016bd85688927fcfca157ba6bf74b08e9439dc010b248ce05b96cc7c126a354c3bae7fcb48b7f - languageName: node - linkType: hard - -"mime-db@npm:1.52.0": - version: 1.52.0 - resolution: "mime-db@npm:1.52.0" - checksum: 10c0/0557a01deebf45ac5f5777fe7740b2a5c309c6d62d40ceab4e23da9f821899ce7a900b7ac8157d4548ddbb7beffe9abc621250e6d182b0397ec7f10c7b91a5aa - languageName: node - linkType: hard - -"mime-types@npm:^2.1.12": - version: 2.1.35 - resolution: "mime-types@npm:2.1.35" - dependencies: - mime-db: "npm:1.52.0" - checksum: 10c0/82fb07ec56d8ff1fc999a84f2f217aa46cb6ed1033fefaabd5785b9a974ed225c90dc72fff460259e66b95b73648596dbcc50d51ed69cdf464af2d237d3149b2 - languageName: node - linkType: hard - -"minimatch@npm:^9.0.4": - version: 9.0.5 - resolution: "minimatch@npm:9.0.5" - dependencies: - brace-expansion: "npm:^2.0.1" - checksum: 10c0/de96cf5e35bdf0eab3e2c853522f98ffbe9a36c37797778d2665231ec1f20a9447a7e567cb640901f89e4daaa95ae5d70c65a9e8aa2bb0019b6facbc3c0575ed - languageName: node - linkType: hard - -"minipass-collect@npm:^2.0.1": - version: 2.0.1 - resolution: "minipass-collect@npm:2.0.1" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e - languageName: node - linkType: hard - -"minipass-fetch@npm:^4.0.0": - version: 4.0.1 - resolution: "minipass-fetch@npm:4.0.1" - dependencies: - encoding: "npm:^0.1.13" - minipass: "npm:^7.0.3" - minipass-sized: "npm:^1.0.3" - minizlib: "npm:^3.0.1" - dependenciesMeta: - encoding: - optional: true - checksum: 10c0/a3147b2efe8e078c9bf9d024a0059339c5a09c5b1dded6900a219c218cc8b1b78510b62dae556b507304af226b18c3f1aeb1d48660283602d5b6586c399eed5c - languageName: node - linkType: hard - -"minipass-flush@npm:^1.0.5": - version: 1.0.5 - resolution: "minipass-flush@npm:1.0.5" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/2a51b63feb799d2bb34669205eee7c0eaf9dce01883261a5b77410c9408aa447e478efd191b4de6fc1101e796ff5892f8443ef20d9544385819093dbb32d36bd - languageName: node - linkType: hard - -"minipass-pipeline@npm:^1.2.4": - version: 1.2.4 - resolution: "minipass-pipeline@npm:1.2.4" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2 - languageName: node - linkType: hard - -"minipass-sized@npm:^1.0.3": - version: 1.0.3 - resolution: "minipass-sized@npm:1.0.3" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb - languageName: node - linkType: hard - -"minipass@npm:^3.0.0": - version: 3.3.6 - resolution: "minipass@npm:3.3.6" - dependencies: - yallist: "npm:^4.0.0" - checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c - languageName: node - linkType: hard - -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": - version: 7.1.2 - resolution: "minipass@npm:7.1.2" - checksum: 10c0/b0fd20bb9fb56e5fa9a8bfac539e8915ae07430a619e4b86ff71f5fc757ef3924b23b2c4230393af1eda647ed3d75739e4e0acb250a6b1eb277cf7f8fe449557 - languageName: node - linkType: hard - -"minizlib@npm:^3.0.1": - version: 3.0.2 - resolution: "minizlib@npm:3.0.2" - dependencies: - minipass: "npm:^7.1.2" - checksum: 10c0/9f3bd35e41d40d02469cb30470c55ccc21cae0db40e08d1d0b1dff01cc8cc89a6f78e9c5d2b7c844e485ec0a8abc2238111213fdc5b2038e6d1012eacf316f78 - languageName: node - linkType: hard - -"mkdirp@npm:^3.0.1": - version: 3.0.1 - resolution: "mkdirp@npm:3.0.1" - bin: - mkdirp: dist/cjs/src/bin.js - checksum: 10c0/9f2b975e9246351f5e3a40dcfac99fcd0baa31fbfab615fe059fb11e51f10e4803c63de1f384c54d656e4db31d000e4767e9ef076a22e12a641357602e31d57d - languageName: node - linkType: hard - -"ms@npm:^2.1.3": - version: 2.1.3 - resolution: "ms@npm:2.1.3" - checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 - languageName: node - linkType: hard - -"nanoevents@npm:^9.1.0": - version: 9.1.0 - resolution: "nanoevents@npm:9.1.0" - checksum: 10c0/5fb48e6fc1d3102daddaeffd6eada907c25b1c8554dcc648e9cb0a72979a1ab3ee56ffa2d2b3e566a8e561a9e2992a3783493c61cfaaa096b2986d56dbbc1ca5 - languageName: node - linkType: hard - -"nanoid@npm:^3.3.11": - version: 3.3.11 - resolution: "nanoid@npm:3.3.11" - bin: - nanoid: bin/nanoid.cjs - checksum: 10c0/40e7f70b3d15f725ca072dfc4f74e81fcf1fbb02e491cf58ac0c79093adc9b0a73b152bcde57df4b79cd097e13023d7504acb38404a4da7bc1cd8e887b82fe0b - languageName: node - linkType: hard - -"negotiator@npm:^1.0.0": - version: 1.0.0 - resolution: "negotiator@npm:1.0.0" - checksum: 10c0/4c559dd52669ea48e1914f9d634227c561221dd54734070791f999c52ed0ff36e437b2e07d5c1f6e32909fc625fe46491c16e4a8f0572567d4dd15c3a4fda04b - languageName: node - linkType: hard - -"node-fetch@npm:2": - version: 2.7.0 - resolution: "node-fetch@npm:2.7.0" - dependencies: - whatwg-url: "npm:^5.0.0" - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - checksum: 10c0/b55786b6028208e6fbe594ccccc213cab67a72899c9234eb59dba51062a299ea853210fcf526998eaa2867b0963ad72338824450905679ff0fa304b8c5093ae8 - languageName: node - linkType: hard - -"node-gyp@npm:latest": - version: 11.2.0 - resolution: "node-gyp@npm:11.2.0" - dependencies: - env-paths: "npm:^2.2.0" - exponential-backoff: "npm:^3.1.1" - graceful-fs: "npm:^4.2.6" - make-fetch-happen: "npm:^14.0.3" - nopt: "npm:^8.0.0" - proc-log: "npm:^5.0.0" - semver: "npm:^7.3.5" - tar: "npm:^7.4.3" - tinyglobby: "npm:^0.2.12" - which: "npm:^5.0.0" - bin: - node-gyp: bin/node-gyp.js - checksum: 10c0/bd8d8c76b06be761239b0c8680f655f6a6e90b48e44d43415b11c16f7e8c15be346fba0cbf71588c7cdfb52c419d928a7d3db353afc1d952d19756237d8f10b9 - languageName: node - linkType: hard - -"nopt@npm:^8.0.0": - version: 8.1.0 - resolution: "nopt@npm:8.1.0" - dependencies: - abbrev: "npm:^3.0.0" - bin: - nopt: bin/nopt.js - checksum: 10c0/62e9ea70c7a3eb91d162d2c706b6606c041e4e7b547cbbb48f8b3695af457dd6479904d7ace600856bf923dd8d1ed0696f06195c8c20f02ac87c1da0e1d315ef - languageName: node - linkType: hard - -"object-inspect@npm:^1.13.3": - version: 1.13.4 - resolution: "object-inspect@npm:1.13.4" - checksum: 10c0/d7f8711e803b96ea3191c745d6f8056ce1f2496e530e6a19a0e92d89b0fa3c76d910c31f0aa270432db6bd3b2f85500a376a83aaba849a8d518c8845b3211692 - languageName: node - linkType: hard - -"p-map@npm:^7.0.2": - version: 7.0.3 - resolution: "p-map@npm:7.0.3" - checksum: 10c0/46091610da2b38ce47bcd1d8b4835a6fa4e832848a6682cf1652bc93915770f4617afc844c10a77d1b3e56d2472bb2d5622353fa3ead01a7f42b04fc8e744a5c - languageName: node - linkType: hard - -"package-json-from-dist@npm:^1.0.0": - version: 1.0.1 - resolution: "package-json-from-dist@npm:1.0.1" - checksum: 10c0/62ba2785eb655fec084a257af34dbe24292ab74516d6aecef97ef72d4897310bc6898f6c85b5cd22770eaa1ce60d55a0230e150fb6a966e3ecd6c511e23d164b - languageName: node - linkType: hard - -"path-key@npm:^3.1.0": - version: 3.1.1 - resolution: "path-key@npm:3.1.1" - checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c - languageName: node - linkType: hard - -"path-scurry@npm:^1.11.1": - version: 1.11.1 - resolution: "path-scurry@npm:1.11.1" - dependencies: - lru-cache: "npm:^10.2.0" - minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - checksum: 10c0/32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d - languageName: node - linkType: hard - -"pathe@npm:^2.0.3": - version: 2.0.3 - resolution: "pathe@npm:2.0.3" - checksum: 10c0/c118dc5a8b5c4166011b2b70608762e260085180bb9e33e80a50dcdb1e78c010b1624f4280c492c92b05fc276715a4c357d1f9edc570f8f1b3d90b6839ebaca1 - languageName: node - linkType: hard - -"pathval@npm:^2.0.0": - version: 2.0.0 - resolution: "pathval@npm:2.0.0" - checksum: 10c0/602e4ee347fba8a599115af2ccd8179836a63c925c23e04bd056d0674a64b39e3a081b643cc7bc0b84390517df2d800a46fcc5598d42c155fe4977095c2f77c5 - languageName: node - linkType: hard - -"picocolors@npm:^1.1.1": - version: 1.1.1 - resolution: "picocolors@npm:1.1.1" - checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58 - languageName: node - linkType: hard - -"picomatch@npm:^4.0.2": - version: 4.0.2 - resolution: "picomatch@npm:4.0.2" - checksum: 10c0/7c51f3ad2bb42c776f49ebf964c644958158be30d0a510efd5a395e8d49cb5acfed5b82c0c5b365523ce18e6ab85013c9ebe574f60305892ec3fa8eee8304ccc - languageName: node - linkType: hard - -"postcss@npm:^8.5.3": - version: 8.5.4 - resolution: "postcss@npm:8.5.4" - dependencies: - nanoid: "npm:^3.3.11" - picocolors: "npm:^1.1.1" - source-map-js: "npm:^1.2.1" - checksum: 10c0/0feff648614a834f7cd5396ea6b05b658ca0507e10a4eaad03b56c348f6aec93f42a885fc1b30522630c6a7e49ae53b38a061e3cba526f2d9857afbe095a22bb - languageName: node - linkType: hard - -"proc-log@npm:^5.0.0": - version: 5.0.0 - resolution: "proc-log@npm:5.0.0" - checksum: 10c0/bbe5edb944b0ad63387a1d5b1911ae93e05ce8d0f60de1035b218cdcceedfe39dbd2c697853355b70f1a090f8f58fe90da487c85216bf9671f9499d1a897e9e3 - languageName: node - linkType: hard - -"process@npm:^0.11.10": - version: 0.11.10 - resolution: "process@npm:0.11.10" - checksum: 10c0/40c3ce4b7e6d4b8c3355479df77aeed46f81b279818ccdc500124e6a5ab882c0cc81ff7ea16384873a95a74c4570b01b120f287abbdd4c877931460eca6084b3 - languageName: node - linkType: hard - -"promise-retry@npm:^2.0.1": - version: 2.0.1 - resolution: "promise-retry@npm:2.0.1" - dependencies: - err-code: "npm:^2.0.2" - retry: "npm:^0.12.0" - checksum: 10c0/9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96 - languageName: node - linkType: hard - -"qs@npm:^6.11.2": - version: 6.14.0 - resolution: "qs@npm:6.14.0" - dependencies: - side-channel: "npm:^1.1.0" - checksum: 10c0/8ea5d91bf34f440598ee389d4a7d95820e3b837d3fd9f433871f7924801becaa0cd3b3b4628d49a7784d06a8aea9bc4554d2b6d8d584e2d221dc06238a42909c - languageName: node - linkType: hard - -"readable-stream@npm:^4.5.2": - version: 4.7.0 - resolution: "readable-stream@npm:4.7.0" - dependencies: - abort-controller: "npm:^3.0.0" - buffer: "npm:^6.0.3" - events: "npm:^3.3.0" - process: "npm:^0.11.10" - string_decoder: "npm:^1.3.0" - checksum: 10c0/fd86d068da21cfdb10f7a4479f2e47d9c0a9b0c862fc0c840a7e5360201580a55ac399c764b12a4f6fa291f8cee74d9c4b7562e0d53b3c4b2769f2c98155d957 - languageName: node - linkType: hard - -"resolve-pkg-maps@npm:^1.0.0": - version: 1.0.0 - resolution: "resolve-pkg-maps@npm:1.0.0" - checksum: 10c0/fb8f7bbe2ca281a73b7ef423a1cbc786fb244bd7a95cbe5c3fba25b27d327150beca8ba02f622baea65919a57e061eb5005204daa5f93ed590d9b77463a567ab - languageName: node - linkType: hard - -"retry@npm:^0.12.0": - version: 0.12.0 - resolution: "retry@npm:0.12.0" - checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe - languageName: node - linkType: hard - -"rollup@npm:^4.40.0": - version: 4.42.0 - resolution: "rollup@npm:4.42.0" - dependencies: - "@rollup/rollup-android-arm-eabi": "npm:4.42.0" - "@rollup/rollup-android-arm64": "npm:4.42.0" - "@rollup/rollup-darwin-arm64": "npm:4.42.0" - "@rollup/rollup-darwin-x64": "npm:4.42.0" - "@rollup/rollup-freebsd-arm64": "npm:4.42.0" - "@rollup/rollup-freebsd-x64": "npm:4.42.0" - "@rollup/rollup-linux-arm-gnueabihf": "npm:4.42.0" - "@rollup/rollup-linux-arm-musleabihf": "npm:4.42.0" - "@rollup/rollup-linux-arm64-gnu": "npm:4.42.0" - "@rollup/rollup-linux-arm64-musl": "npm:4.42.0" - "@rollup/rollup-linux-loongarch64-gnu": "npm:4.42.0" - "@rollup/rollup-linux-powerpc64le-gnu": "npm:4.42.0" - "@rollup/rollup-linux-riscv64-gnu": "npm:4.42.0" - "@rollup/rollup-linux-riscv64-musl": "npm:4.42.0" - "@rollup/rollup-linux-s390x-gnu": "npm:4.42.0" - "@rollup/rollup-linux-x64-gnu": "npm:4.42.0" - "@rollup/rollup-linux-x64-musl": "npm:4.42.0" - "@rollup/rollup-win32-arm64-msvc": "npm:4.42.0" - "@rollup/rollup-win32-ia32-msvc": "npm:4.42.0" - "@rollup/rollup-win32-x64-msvc": "npm:4.42.0" - "@types/estree": "npm:1.0.7" - fsevents: "npm:~2.3.2" - dependenciesMeta: - "@rollup/rollup-android-arm-eabi": - optional: true - "@rollup/rollup-android-arm64": - optional: true - "@rollup/rollup-darwin-arm64": - optional: true - "@rollup/rollup-darwin-x64": - optional: true - "@rollup/rollup-freebsd-arm64": - optional: true - "@rollup/rollup-freebsd-x64": - optional: true - "@rollup/rollup-linux-arm-gnueabihf": - optional: true - "@rollup/rollup-linux-arm-musleabihf": - optional: true - "@rollup/rollup-linux-arm64-gnu": - optional: true - "@rollup/rollup-linux-arm64-musl": - optional: true - "@rollup/rollup-linux-loongarch64-gnu": - optional: true - "@rollup/rollup-linux-powerpc64le-gnu": - optional: true - "@rollup/rollup-linux-riscv64-gnu": - optional: true - "@rollup/rollup-linux-riscv64-musl": - optional: true - "@rollup/rollup-linux-s390x-gnu": - optional: true - "@rollup/rollup-linux-x64-gnu": - optional: true - "@rollup/rollup-linux-x64-musl": - optional: true - "@rollup/rollup-win32-arm64-msvc": - optional: true - "@rollup/rollup-win32-ia32-msvc": - optional: true - "@rollup/rollup-win32-x64-msvc": - optional: true - fsevents: - optional: true - bin: - rollup: dist/bin/rollup - checksum: 10c0/160fdb0874af5f0f619987b4e9abb3b136fc154f759762bfde4d65d864d6d06594ae7d1d8e6d4558d1b8ef329aaa6a8de543e90feead3d872db15cf61f78426c - languageName: node - linkType: hard - -"safe-buffer@npm:~5.2.0": - version: 5.2.1 - resolution: "safe-buffer@npm:5.2.1" - checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 - languageName: node - linkType: hard - -"safer-buffer@npm:>= 2.1.2 < 3.0.0": - version: 2.1.2 - resolution: "safer-buffer@npm:2.1.2" - checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 - languageName: node - linkType: hard - -"semver@npm:^7.3.5": - version: 7.7.2 - resolution: "semver@npm:7.7.2" - bin: - semver: bin/semver.js - checksum: 10c0/aca305edfbf2383c22571cb7714f48cadc7ac95371b4b52362fb8eeffdfbc0de0669368b82b2b15978f8848f01d7114da65697e56cd8c37b0dab8c58e543f9ea - languageName: node - linkType: hard - -"shebang-command@npm:^2.0.0": - version: 2.0.0 - resolution: "shebang-command@npm:2.0.0" - dependencies: - shebang-regex: "npm:^3.0.0" - checksum: 10c0/a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e - languageName: node - linkType: hard - -"shebang-regex@npm:^3.0.0": - version: 3.0.0 - resolution: "shebang-regex@npm:3.0.0" - checksum: 10c0/1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 - languageName: node - linkType: hard - -"side-channel-list@npm:^1.0.0": - version: 1.0.0 - resolution: "side-channel-list@npm:1.0.0" - dependencies: - es-errors: "npm:^1.3.0" - object-inspect: "npm:^1.13.3" - checksum: 10c0/644f4ac893456c9490ff388bf78aea9d333d5e5bfc64cfb84be8f04bf31ddc111a8d4b83b85d7e7e8a7b845bc185a9ad02c052d20e086983cf59f0be517d9b3d - languageName: node - linkType: hard - -"side-channel-map@npm:^1.0.1": - version: 1.0.1 - resolution: "side-channel-map@npm:1.0.1" - dependencies: - call-bound: "npm:^1.0.2" - es-errors: "npm:^1.3.0" - get-intrinsic: "npm:^1.2.5" - object-inspect: "npm:^1.13.3" - checksum: 10c0/010584e6444dd8a20b85bc926d934424bd809e1a3af941cace229f7fdcb751aada0fb7164f60c2e22292b7fa3c0ff0bce237081fd4cdbc80de1dc68e95430672 - languageName: node - linkType: hard - -"side-channel-weakmap@npm:^1.0.2": - version: 1.0.2 - resolution: "side-channel-weakmap@npm:1.0.2" - dependencies: - call-bound: "npm:^1.0.2" - es-errors: "npm:^1.3.0" - get-intrinsic: "npm:^1.2.5" - object-inspect: "npm:^1.13.3" - side-channel-map: "npm:^1.0.1" - checksum: 10c0/71362709ac233e08807ccd980101c3e2d7efe849edc51455030327b059f6c4d292c237f94dc0685031dd11c07dd17a68afde235d6cf2102d949567f98ab58185 - languageName: node - linkType: hard - -"side-channel@npm:^1.1.0": - version: 1.1.0 - resolution: "side-channel@npm:1.1.0" - dependencies: - es-errors: "npm:^1.3.0" - object-inspect: "npm:^1.13.3" - side-channel-list: "npm:^1.0.0" - side-channel-map: "npm:^1.0.1" - side-channel-weakmap: "npm:^1.0.2" - checksum: 10c0/cb20dad41eb032e6c24c0982e1e5a24963a28aa6122b4f05b3f3d6bf8ae7fd5474ef382c8f54a6a3ab86e0cac4d41a23bd64ede3970e5bfb50326ba02a7996e6 - languageName: node - linkType: hard - -"siginfo@npm:^2.0.0": - version: 2.0.0 - resolution: "siginfo@npm:2.0.0" - checksum: 10c0/3def8f8e516fbb34cb6ae415b07ccc5d9c018d85b4b8611e3dc6f8be6d1899f693a4382913c9ed51a06babb5201639d76453ab297d1c54a456544acf5c892e34 - languageName: node - linkType: hard - -"signal-exit@npm:^4.0.1": - version: 4.1.0 - resolution: "signal-exit@npm:4.1.0" - checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 - languageName: node - linkType: hard - -"smart-buffer@npm:^4.2.0": - version: 4.2.0 - resolution: "smart-buffer@npm:4.2.0" - checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539 - languageName: node - linkType: hard - -"socks-proxy-agent@npm:^8.0.3": - version: 8.0.5 - resolution: "socks-proxy-agent@npm:8.0.5" - dependencies: - agent-base: "npm:^7.1.2" - debug: "npm:^4.3.4" - socks: "npm:^2.8.3" - checksum: 10c0/5d2c6cecba6821389aabf18728325730504bf9bb1d9e342e7987a5d13badd7a98838cc9a55b8ed3cb866ad37cc23e1086f09c4d72d93105ce9dfe76330e9d2a6 - languageName: node - linkType: hard - -"socks@npm:^2.8.3": - version: 2.8.4 - resolution: "socks@npm:2.8.4" - dependencies: - ip-address: "npm:^9.0.5" - smart-buffer: "npm:^4.2.0" - checksum: 10c0/00c3271e233ccf1fb83a3dd2060b94cc37817e0f797a93c560b9a7a86c4a0ec2961fb31263bdd24a3c28945e24868b5f063cd98744171d9e942c513454b50ae5 - languageName: node - linkType: hard - -"source-map-js@npm:^1.2.1": - version: 1.2.1 - resolution: "source-map-js@npm:1.2.1" - checksum: 10c0/7bda1fc4c197e3c6ff17de1b8b2c20e60af81b63a52cb32ec5a5d67a20a7d42651e2cb34ebe93833c5a2a084377e17455854fee3e21e7925c64a51b6a52b0faf - languageName: node - linkType: hard - -"sprintf-js@npm:^1.1.3": - version: 1.1.3 - resolution: "sprintf-js@npm:1.1.3" - checksum: 10c0/09270dc4f30d479e666aee820eacd9e464215cdff53848b443964202bf4051490538e5dd1b42e1a65cf7296916ca17640aebf63dae9812749c7542ee5f288dec - languageName: node - linkType: hard - -"ssri@npm:^12.0.0": - version: 12.0.0 - resolution: "ssri@npm:12.0.0" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/caddd5f544b2006e88fa6b0124d8d7b28208b83c72d7672d5ade44d794525d23b540f3396108c4eb9280dcb7c01f0bef50682f5b4b2c34291f7c5e211fd1417d - languageName: node - linkType: hard - -"stackback@npm:0.0.2": - version: 0.0.2 - resolution: "stackback@npm:0.0.2" - checksum: 10c0/89a1416668f950236dd5ac9f9a6b2588e1b9b62b1b6ad8dff1bfc5d1a15dbf0aafc9b52d2226d00c28dffff212da464eaeebfc6b7578b9d180cef3e3782c5983 - languageName: node - linkType: hard - -"std-env@npm:^3.9.0": - version: 3.9.0 - resolution: "std-env@npm:3.9.0" - checksum: 10c0/4a6f9218aef3f41046c3c7ecf1f98df00b30a07f4f35c6d47b28329bc2531eef820828951c7d7b39a1c5eb19ad8a46e3ddfc7deb28f0a2f3ceebee11bab7ba50 - languageName: node - linkType: hard - -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0": - version: 4.2.3 - resolution: "string-width@npm:4.2.3" - dependencies: - emoji-regex: "npm:^8.0.0" - is-fullwidth-code-point: "npm:^3.0.0" - strip-ansi: "npm:^6.0.1" - checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b - languageName: node - linkType: hard - -"string-width@npm:^5.0.1, string-width@npm:^5.1.2": - version: 5.1.2 - resolution: "string-width@npm:5.1.2" - dependencies: - eastasianwidth: "npm:^0.2.0" - emoji-regex: "npm:^9.2.2" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca - languageName: node - linkType: hard - -"string_decoder@npm:^1.3.0": - version: 1.3.0 - resolution: "string_decoder@npm:1.3.0" - dependencies: - safe-buffer: "npm:~5.2.0" - checksum: 10c0/810614ddb030e271cd591935dcd5956b2410dd079d64ff92a1844d6b7588bf992b3e1b69b0f4d34a3e06e0bd73046ac646b5264c1987b20d0601f81ef35d731d - languageName: node - linkType: hard - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": - version: 6.0.1 - resolution: "strip-ansi@npm:6.0.1" - dependencies: - ansi-regex: "npm:^5.0.1" - checksum: 10c0/1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952 - languageName: node - linkType: hard - -"strip-ansi@npm:^7.0.1": - version: 7.1.0 - resolution: "strip-ansi@npm:7.1.0" - dependencies: - ansi-regex: "npm:^6.0.1" - checksum: 10c0/a198c3762e8832505328cbf9e8c8381de14a4fa50a4f9b2160138158ea88c0f5549fb50cb13c651c3088f47e63a108b34622ec18c0499b6c8c3a5ddf6b305ac4 - languageName: node - linkType: hard - -"strip-literal@npm:^3.0.0": - version: 3.0.0 - resolution: "strip-literal@npm:3.0.0" - dependencies: - js-tokens: "npm:^9.0.1" - checksum: 10c0/d81657f84aba42d4bbaf2a677f7e7f34c1f3de5a6726db8bc1797f9c0b303ba54d4660383a74bde43df401cf37cce1dff2c842c55b077a4ceee11f9e31fba828 - languageName: node - linkType: hard - -"tar@npm:^7.4.3": - version: 7.4.3 - resolution: "tar@npm:7.4.3" - dependencies: - "@isaacs/fs-minipass": "npm:^4.0.0" - chownr: "npm:^3.0.0" - minipass: "npm:^7.1.2" - minizlib: "npm:^3.0.1" - mkdirp: "npm:^3.0.1" - yallist: "npm:^5.0.0" - checksum: 10c0/d4679609bb2a9b48eeaf84632b6d844128d2412b95b6de07d53d8ee8baf4ca0857c9331dfa510390a0727b550fd543d4d1a10995ad86cdf078423fbb8d99831d - languageName: node - linkType: hard - -"tinybench@npm:^2.9.0": - version: 2.9.0 - resolution: "tinybench@npm:2.9.0" - checksum: 10c0/c3500b0f60d2eb8db65250afe750b66d51623057ee88720b7f064894a6cb7eb93360ca824a60a31ab16dab30c7b1f06efe0795b352e37914a9d4bad86386a20c - languageName: node - linkType: hard - -"tinyexec@npm:^0.3.2": - version: 0.3.2 - resolution: "tinyexec@npm:0.3.2" - checksum: 10c0/3efbf791a911be0bf0821eab37a3445c2ba07acc1522b1fa84ae1e55f10425076f1290f680286345ed919549ad67527d07281f1c19d584df3b74326909eb1f90 - languageName: node - linkType: hard - -"tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.14": - version: 0.2.14 - resolution: "tinyglobby@npm:0.2.14" - dependencies: - fdir: "npm:^6.4.4" - picomatch: "npm:^4.0.2" - checksum: 10c0/f789ed6c924287a9b7d3612056ed0cda67306cd2c80c249fd280cf1504742b12583a2089b61f4abbd24605f390809017240e250241f09938054c9b363e51c0a6 - languageName: node - linkType: hard - -"tinypool@npm:^1.1.0": - version: 1.1.0 - resolution: "tinypool@npm:1.1.0" - checksum: 10c0/deb6bde5e3d85d4ba043806c66f43fb5b649716312a47b52761a83668ffc71cd0ea4e24254c1b02a3702e5c27e02605f0189a1460f6284a5930a08bd0c06435c - languageName: node - linkType: hard - -"tinyrainbow@npm:^2.0.0": - version: 2.0.0 - resolution: "tinyrainbow@npm:2.0.0" - checksum: 10c0/c83c52bef4e0ae7fb8ec6a722f70b5b6fa8d8be1c85792e829f56c0e1be94ab70b293c032dc5048d4d37cfe678f1f5babb04bdc65fd123098800148ca989184f - languageName: node - linkType: hard - -"tinyspy@npm:^4.0.3": - version: 4.0.3 - resolution: "tinyspy@npm:4.0.3" - checksum: 10c0/0a92a18b5350945cc8a1da3a22c9ad9f4e2945df80aaa0c43e1b3a3cfb64d8501e607ebf0305e048e3c3d3e0e7f8eb10cea27dc17c21effb73e66c4a3be36373 - languageName: node - linkType: hard - -"tr46@npm:~0.0.3": - version: 0.0.3 - resolution: "tr46@npm:0.0.3" - checksum: 10c0/047cb209a6b60c742f05c9d3ace8fa510bff609995c129a37ace03476a9b12db4dbf975e74600830ef0796e18882b2381fb5fb1f6b4f96b832c374de3ab91a11 - languageName: node - linkType: hard - -"tsx@npm:^4.19.4": - version: 4.19.4 - resolution: "tsx@npm:4.19.4" - dependencies: - esbuild: "npm:~0.25.0" - fsevents: "npm:~2.3.3" - get-tsconfig: "npm:^4.7.5" - dependenciesMeta: - fsevents: - optional: true - bin: - tsx: dist/cli.mjs - checksum: 10c0/f7b8d44362343fbde1f2ecc9832d243a450e1168dd09702a545ebe5f699aa6912e45b431a54b885466db414cceda48e5067b36d182027c43b2c02a4f99d8721e - languageName: node - linkType: hard - -"typescript@npm:^5.7.2": - version: 5.8.3 - resolution: "typescript@npm:5.8.3" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10c0/5f8bb01196e542e64d44db3d16ee0e4063ce4f3e3966df6005f2588e86d91c03e1fb131c2581baf0fb65ee79669eea6e161cd448178986587e9f6844446dbb48 - languageName: node - linkType: hard - -"typescript@patch:typescript@npm%3A^5.7.2#optional!builtin": - version: 5.8.3 - resolution: "typescript@patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10c0/39117e346ff8ebd87ae1510b3a77d5d92dae5a89bde588c747d25da5c146603a99c8ee588c7ef80faaf123d89ed46f6dbd918d534d641083177d5fac38b8a1cb - languageName: node - linkType: hard - -"undici-types@npm:~6.21.0": - version: 6.21.0 - resolution: "undici-types@npm:6.21.0" - checksum: 10c0/c01ed51829b10aa72fc3ce64b747f8e74ae9b60eafa19a7b46ef624403508a54c526ffab06a14a26b3120d055e1104d7abe7c9017e83ced038ea5cf52f8d5e04 - languageName: node - linkType: hard - -"unique-filename@npm:^4.0.0": - version: 4.0.0 - resolution: "unique-filename@npm:4.0.0" - dependencies: - unique-slug: "npm:^5.0.0" - checksum: 10c0/38ae681cceb1408ea0587b6b01e29b00eee3c84baee1e41fd5c16b9ed443b80fba90c40e0ba69627e30855570a34ba8b06702d4a35035d4b5e198bf5a64c9ddc - languageName: node - linkType: hard - -"unique-slug@npm:^5.0.0": - version: 5.0.0 - resolution: "unique-slug@npm:5.0.0" - dependencies: - imurmurhash: "npm:^0.1.4" - checksum: 10c0/d324c5a44887bd7e105ce800fcf7533d43f29c48757ac410afd42975de82cc38ea2035c0483f4de82d186691bf3208ef35c644f73aa2b1b20b8e651be5afd293 - languageName: node - linkType: hard - -"url-join@npm:^5.0.0": - version: 5.0.0 - resolution: "url-join@npm:5.0.0" - checksum: 10c0/ed2b166b4b5a98adcf6828a48b6bd6df1dac4c8a464a73cf4d8e2457ed410dd8da6be0d24855b86026cd7f5c5a3657c1b7b2c7a7c5b8870af17635a41387b04c - languageName: node - linkType: hard - -"vite-node@npm:3.2.3": - version: 3.2.3 - resolution: "vite-node@npm:3.2.3" - dependencies: - cac: "npm:^6.7.14" - debug: "npm:^4.4.1" - es-module-lexer: "npm:^1.7.0" - pathe: "npm:^2.0.3" - vite: "npm:^5.0.0 || ^6.0.0 || ^7.0.0-0" - bin: - vite-node: vite-node.mjs - checksum: 10c0/b952b0d9e45662506ea7303ac87d08e02f1e3355777cf7d426f211292c4f87e8837aef589e552bb11404d1bc0a9bd18871ce6ba874b5f0bb171f8e010de20a11 - languageName: node - linkType: hard - -"vite@npm:^5.0.0 || ^6.0.0 || ^7.0.0-0": - version: 7.0.0-beta.0 - resolution: "vite@npm:7.0.0-beta.0" - dependencies: - esbuild: "npm:^0.25.0" - fdir: "npm:^6.4.4" - fsevents: "npm:~2.3.3" - picomatch: "npm:^4.0.2" - postcss: "npm:^8.5.3" - rollup: "npm:^4.40.0" - tinyglobby: "npm:^0.2.14" - peerDependencies: - "@types/node": ^20.19.0 || >=22.12.0 - jiti: ">=1.21.0" - less: ^4.0.0 - lightningcss: ^1.21.0 - sass: ^1.70.0 - sass-embedded: ^1.70.0 - stylus: ">=0.54.8" - sugarss: ^5.0.0 - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - dependenciesMeta: - fsevents: - optional: true - peerDependenciesMeta: - "@types/node": - optional: true - jiti: - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true - bin: - vite: bin/vite.js - checksum: 10c0/d13907d67b4991a2862dafe6a31d10ffe28f26ba04e511049e9d86d06293b3a8d6733c896c8fb38e3f2d5805d240e3cad27700f3c42536602035e4c324b48d58 - languageName: node - linkType: hard - -"vitest@npm:^3.2.2": - version: 3.2.3 - resolution: "vitest@npm:3.2.3" - dependencies: - "@types/chai": "npm:^5.2.2" - "@vitest/expect": "npm:3.2.3" - "@vitest/mocker": "npm:3.2.3" - "@vitest/pretty-format": "npm:^3.2.3" - "@vitest/runner": "npm:3.2.3" - "@vitest/snapshot": "npm:3.2.3" - "@vitest/spy": "npm:3.2.3" - "@vitest/utils": "npm:3.2.3" - chai: "npm:^5.2.0" - debug: "npm:^4.4.1" - expect-type: "npm:^1.2.1" - magic-string: "npm:^0.30.17" - pathe: "npm:^2.0.3" - picomatch: "npm:^4.0.2" - std-env: "npm:^3.9.0" - tinybench: "npm:^2.9.0" - tinyexec: "npm:^0.3.2" - tinyglobby: "npm:^0.2.14" - tinypool: "npm:^1.1.0" - tinyrainbow: "npm:^2.0.0" - vite: "npm:^5.0.0 || ^6.0.0 || ^7.0.0-0" - vite-node: "npm:3.2.3" - why-is-node-running: "npm:^2.3.0" - peerDependencies: - "@edge-runtime/vm": "*" - "@types/debug": ^4.1.12 - "@types/node": ^18.0.0 || ^20.0.0 || >=22.0.0 - "@vitest/browser": 3.2.3 - "@vitest/ui": 3.2.3 - happy-dom: "*" - jsdom: "*" - peerDependenciesMeta: - "@edge-runtime/vm": - optional: true - "@types/debug": - optional: true - "@types/node": - optional: true - "@vitest/browser": - optional: true - "@vitest/ui": - optional: true - happy-dom: - optional: true - jsdom: - optional: true - bin: - vitest: vitest.mjs - checksum: 10c0/1d853016622f32020e91cc72348d0dc642bde2ddcbd648655a9d33d420375c7cbd6f1a6f5c4398a5d4f59b8c2b120e62eba49fb37f8042e5d4c688b7e60148ef - languageName: node - linkType: hard - -"webidl-conversions@npm:^3.0.0": - version: 3.0.1 - resolution: "webidl-conversions@npm:3.0.1" - checksum: 10c0/5612d5f3e54760a797052eb4927f0ddc01383550f542ccd33d5238cfd65aeed392a45ad38364970d0a0f4fea32e1f4d231b3d8dac4a3bdd385e5cf802ae097db - languageName: node - linkType: hard - -"whatwg-url@npm:^5.0.0": - version: 5.0.0 - resolution: "whatwg-url@npm:5.0.0" - dependencies: - tr46: "npm:~0.0.3" - webidl-conversions: "npm:^3.0.0" - checksum: 10c0/1588bed84d10b72d5eec1d0faa0722ba1962f1821e7539c535558fb5398d223b0c50d8acab950b8c488b4ba69043fd833cc2697056b167d8ad46fac3995a55d5 - languageName: node - linkType: hard - -"which@npm:^2.0.1": - version: 2.0.2 - resolution: "which@npm:2.0.2" - dependencies: - isexe: "npm:^2.0.0" - bin: - node-which: ./bin/node-which - checksum: 10c0/66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f - languageName: node - linkType: hard - -"which@npm:^5.0.0": - version: 5.0.0 - resolution: "which@npm:5.0.0" - dependencies: - isexe: "npm:^3.1.1" - bin: - node-which: bin/which.js - checksum: 10c0/e556e4cd8b7dbf5df52408c9a9dd5ac6518c8c5267c8953f5b0564073c66ed5bf9503b14d876d0e9c7844d4db9725fb0dcf45d6e911e17e26ab363dc3965ae7b - languageName: node - linkType: hard - -"why-is-node-running@npm:^2.3.0": - version: 2.3.0 - resolution: "why-is-node-running@npm:2.3.0" - dependencies: - siginfo: "npm:^2.0.0" - stackback: "npm:0.0.2" - bin: - why-is-node-running: cli.js - checksum: 10c0/1cde0b01b827d2cf4cb11db962f3958b9175d5d9e7ac7361d1a7b0e2dc6069a263e69118bd974c4f6d0a890ef4eedfe34cf3d5167ec14203dbc9a18620537054 - languageName: node - linkType: hard - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version: 7.0.0 - resolution: "wrap-ansi@npm:7.0.0" - dependencies: - ansi-styles: "npm:^4.0.0" - string-width: "npm:^4.1.0" - strip-ansi: "npm:^6.0.0" - checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da - languageName: node - linkType: hard - -"wrap-ansi@npm:^8.1.0": - version: 8.1.0 - resolution: "wrap-ansi@npm:8.1.0" - dependencies: - ansi-styles: "npm:^6.1.0" - string-width: "npm:^5.0.1" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 - languageName: node - linkType: hard - -"yallist@npm:^4.0.0": - version: 4.0.0 - resolution: "yallist@npm:4.0.0" - checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a - languageName: node - linkType: hard - -"yallist@npm:^5.0.0": - version: 5.0.0 - resolution: "yallist@npm:5.0.0" - checksum: 10c0/a499c81ce6d4a1d260d4ea0f6d49ab4da09681e32c3f0472dee16667ed69d01dae63a3b81745a24bd78476ec4fcf856114cb4896ace738e01da34b2c42235416 - languageName: node - linkType: hard - -"zod@npm:^3.25.56": - version: 3.25.56 - resolution: "zod@npm:3.25.56" - checksum: 10c0/3800f01d4b1df932b91354eb1e648f69cc7e5561549e6d2bf83827d930a5f33bbf92926099445f6fc1ebb64ca9c6513ef9ae5e5409cfef6325f354bcf6fc9a24 - languageName: node - linkType: hard - -"zx@npm:^8.1.9": - version: 8.5.5 - resolution: "zx@npm:8.5.5" - bin: - zx: build/cli.js - checksum: 10c0/9c69e5a75b49b796211812625564980d0a86079a11011b397c4c77d256e3fe0a76b5ec7134db4d598e156f84e07981d8692544715feb8ff77adfae60faa356fc - languageName: node - linkType: hard diff --git a/cloud/packages/ci-runner/Dockerfile b/cloud/packages/ci-runner/Dockerfile deleted file mode 100644 index 8bbf748c20..0000000000 --- a/cloud/packages/ci-runner/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM alpine:latest AS builder - -# FROM gcr.io/kaniko-project/executor:latest -FROM ghcr.io/rivet-gg/executor@sha256:439d4dbb0f3f8c1c6c2195e144d29195b4930b87166a6fae32061b564a6baa9e -COPY --from=builder /bin/sh /bin/sh -COPY --from=builder /lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.so.1 - -COPY entry.sh ~/entry.sh - -ENTRYPOINT ["/bin/sh", "~/entry.sh"] diff --git a/cloud/packages/ci-runner/entry.sh b/cloud/packages/ci-runner/entry.sh deleted file mode 100644 index 7b0d42e192..0000000000 --- a/cloud/packages/ci-runner/entry.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -# Kaniko args are passed as a single string and -# are split by the entrypoint script. - -# Keep in sync with ci-manager/common.ts -UNIT_SEP_CHAR=$'\x1F' - -# We split the string by the unit separator character -# into an array of words ($@), which preserves any -# spaces in the arguments. -export IFS=$UNIT_SEP_CHAR -set -- $KANIKO_ARGS - -# For build args, values containing spaces are not natively supported by -# Kaniko, they recommend setting IFS to null before command. -export IFS='' -/kaniko/executor $@ \ No newline at end of file diff --git a/cloud/rivet.json b/cloud/rivet.json deleted file mode 100644 index 08356e63c5..0000000000 --- a/cloud/rivet.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "actors": { - "ci-manager": { - "dockerfile": "packages/ci-manager/Dockerfile", - "build_path": "packages/ci-manager" - }, - "ci-runner": { - "dockerfile": "packages/ci-runner/Dockerfile", - "build_path": "packages/ci-runner", - "unstable": { - "allow_root": true - } - } - } -} diff --git a/dev-docs/ACTOR_KEY_RESERVATION.md b/dev-docs/ACTOR_KEY_RESERVATION.md new file mode 100644 index 0000000000..a54105dfc5 --- /dev/null +++ b/dev-docs/ACTOR_KEY_RESERVATION.md @@ -0,0 +1,101 @@ +# Actor Key Reservation + +Epoxy is used to globally store which datacenter an actor lives in for a given actor ID. + +## Schema + +In Epoxy KV store: `Actor key -> reservation ID` + +The reservation ID includes the datacenter of where the actor lives. + +## Consistency Limitations + +Actors have 2 touch points with Epoxy: + +- Reserve actor key (epaxos fast path = 1 RTT, epaxos slow path = 2 RTT) +- Resolve actor ID for key (fast path = 0 RTT, slow path = 1 RTT to nearest DC that has the key) + +Resolving actor ID uses `kv_get_optimistic`, which assumes a value does not change after being set. This allows us to cache the actor's datacenter locally and never have to read from other nodes once we've resolved it once. + +## Reservation ID + +A reservation ID is a unique ID (which includes the datacenter label). + +**Why not store the actor ID** + +Actor IDs initially make sense to use since they include the datacenter ID that the actor lives in. + +Actor IDs can be created and destroyed, but our consistency limitations above requires that we do not change the value after set. Therefore, because we cannot update keys to new actor IDs, we cannot store the actor ID. + +**Why not store just the datacenter label** + +A naiive approach would be to store just the datacenter label in epoxy where the actor lives. + +See reservation chains below. + +### Reservation Chains & Moving Reservation Datacenters (Future Work) + +Eventually, actors need to be moved between datacenters OR destroyed then create in a different datacenter. + +To do this, we'll set up reservation ID chains. Reservation ID chains are used to resolve where a reservation was moved to. When attempting to resolve a reservation that was moved, that datacenter will return the pointer to the reservation that it was moved to. + +Consider: + +- Actor 1 created in DC A with key "foo" + - Generates reservation ID X (in DC A) + - Epoxy stores: foo = reservation X +- Actor 1 destroyed +- Actor 2 created in DC B with key "foo" + - Generations reservation ID Y (in DC B) + - DC A stores pointer from reservation X to reservation Y + - Epoxy still has: foo = reservation X (does not get updated) +- Next request to key "foo": + - Read reservation ID X (in DC A) from Epoxy + - Client send request to DC A with reservation ID X + - DC A returns pointer to reservation ID Y (in DC B) + - Client caches this pointer + - Client sends request to DC B with reservation ID Y +- If the client requests key "foo" again: + - Read reservation ID X (in DC A) from Epoxy + - Client reads cache for reservation X to reservation Y (in DC B) + - Sends request to DC B + +The resulting state is: + +``` +Epoxy: +- foo = reservation X (in DC A) + +Pointer cache (DC A): +- Reservation X (in DC A) -> reservation Y (in DC B) +``` + +**Why not just use datacenter label** + +Consider a chain of pointers between the following datacenters: + +``` +DC label: 1 -> 2 -> 1 -> 3 +Pointer: A B C +``` + +There is a race condition & possible infinite loop when: + +- DC 2 has pointer to DC 1 (pointer B) +- DC 1 still has pointer to DC 2 (pointer A) (has not updated to DC 3, pointer C) + +Using unique reservation IDs allow us to create IDs like `{dc}.{unique}`. The chain would look like: + +``` +Reservation ID: 1.1 -> 2.2 -> 1.3 -> 3.4 +Pointer: A B C +``` + +Now there cannot be a loop between DC 1 & 2 since clients will follow the chain of pointers. + +_This section needs more elaboration on edge cases._ + +## Current Limitation: Keys are tied to a datacenter + +Because we cannot change the value of the reservation ID, actors can only be created in the original for a given ID. + diff --git a/dev-docs/API.md b/dev-docs/API.md new file mode 100644 index 0000000000..96b8d6bfed --- /dev/null +++ b/dev-docs/API.md @@ -0,0 +1,11 @@ +# API + +## Packages + +- `packages/common/api-types`: + - `src/{}/mod.rs`: Common API types shared between multiple packages. + - `src/{}/{}.rs`: Request types used in api-peer (e.g. `get`, `list`). This is not in `rivet-api-peer` because these types must be used with `rivet-api-client` in packaes that don't depend ont `rivet-api-peer` (often because of cirular dependency issues, e.g. `rivet-api-peer` -> `pegboard` -> `rivet-api-peer`) +- `packages/common/api-client`: Helper utilities for making requests to `api-peer` +- `packages/common/api-builder`: Helper utilities for building API servers with Axum +- `packages/services/api-peer`: API endpoint used for peer-to-peer communication across datacenters, only used by internal Rivet packages +- `packages/services/api-public`: API endpoints used by clients calling Rivet APIs diff --git a/dev-docs/DOCKER.md b/dev-docs/DOCKER.md new file mode 100644 index 0000000000..a4397e0f70 --- /dev/null +++ b/dev-docs/DOCKER.md @@ -0,0 +1,5 @@ +# Runner Docker Compose + +`docker compose -f ./docker/dev/docker-compose.yml up --build` + +> Sometimes adding `--force-recreate` is required to get it to deploy the new build diff --git a/dev-docs/ERRORS.md b/dev-docs/ERRORS.md new file mode 100644 index 0000000000..2b984c6805 --- /dev/null +++ b/dev-docs/ERRORS.md @@ -0,0 +1,13 @@ +# Errors + +## RivetError + +TODO: Document the derive macro +TODO: Document .build() -> anyhow + +## Error chains + +- TODO: use `.chain().filter_map(|x| x.downcast_ref::())` otherwise it'll only check the top-most error +- TODO: use `#[source]` in thiserror variants in order for wrapped errors to show up in `.chain()` +- TODO: `#[from]` automatically adds `#[source]` + diff --git a/dev-docs/GUARD.md b/dev-docs/GUARD.md new file mode 100644 index 0000000000..c9d7b06afa --- /dev/null +++ b/dev-docs/GUARD.md @@ -0,0 +1,76 @@ +# Guard Routing & Retry Behavior + +## Guard Core - Retry Behavior + +The retry mechanism enables optimistic routing with cache invalidation: + +- **Fast path with cached routes**: Guard uses cached routing information to avoid expensive database lookups on every request, providing low-latency routing decisions +- **Graceful cache invalidation**: When actors are stopped, destroyed, or moved to different runners, the cache becomes stale. Rather than proactively invalidating cache entries (which would require complex coordination), any failure response signals that the cached route is invalid +- **Fresh service discovery on retry**: Retry attempts ignore the cache and perform fresh database lookups to discover current actor locations, ensuring requests reach the correct destination + +This approach optimizes for the common case (actors are running and routes are valid) while gracefully handling the uncommon case (actors have moved/stopped) without sacrificing performance + +### Retry Flow + +**Initial Request (Attempt 1)**: + +1. Check route cache for target location +2. If cached route exists, send request to cached target +3. If request succeeds → return response to client +4. If request fails with retry-able error → proceed to retry + +**Retry Attempts (Attempts 2-N)**: + +1. Wait for exponential backoff delay (100ms × 2^(attempt-2)) +2. **Ignore cache** and perform fresh database lookup for target location +3. Send request to newly discovered target +4. If request succeeds → return response to client +5. If request fails and max attempts not reached → repeat retry flow +6. If max attempts exceeded → return `502 Bad Gateway` to client + +**Configuration**: + +- **Exponential backoff**: Starting interval 100ms, doubles each attempt (100ms, 200ms, 400ms...) +- **Maximum attempts**: Default 3 total attempts +- **Retry triggers**: TCP connection errors OR `503 Service Unavailable` with `x-rivet-error` header + +### Expected Service Response for Retries + +Services that want to trigger guard retries must respond with: + +- `503 Service Unavailable` status code +- `x-rivet-error: ` header + +## Guard Router - Routing Logic + +### Routing Priority + +Requests are routed in the following priority order: + +#### 1. Target-Based Routing (Header: `x-rivet-target`) + +When the `x-rivet-target` header is present, routes to specific service types: + +**Actor Services** (`x-rivet-target: actor`): +- **Required headers**: + - `x-rivet-actor: ` - UUID of the specific actor instance +- **Optional headers**: + - `x-rivet-addr:
` - Direct address override for actor location +- **Behavior**: Routes to the specific actor instance, with cross-datacenter routing if the actor resides in a different DC + +**Runner WebSocket** (`x-rivet-target: runner-ws`): +- **Purpose**: Routes WebSocket connections to the Pegboard runner service +- **Target**: Routes to the configured Pegboard service (`pegboard.lan_host:pegboard.port`) +- **Use case**: WebSocket connections between runners and the orchestration system + +#### 2. API Routing (No target header) + +When no `x-rivet-target` header is present: +- **Target**: Routes to the public API service (`api_public.lan_host:api_public.port`) +- **Behavior**: Standard HTTP API requests for general application functionality +- **Path preservation**: The original request path is preserved in the upstream request + +#### 3. Fallback + +Returns `404 Not Found` if no routing rules match. + diff --git a/dev-docs/PEGBOARD_TUNNEL_RETRIES.md b/dev-docs/PEGBOARD_TUNNEL_RETRIES.md new file mode 100644 index 0000000000..132d721b70 --- /dev/null +++ b/dev-docs/PEGBOARD_TUNNEL_RETRIES.md @@ -0,0 +1,83 @@ +# Pegboard Tunnel Retries + +_TODO: Clean up this AI slop explanation_ + +This document explains how retries are coordinated between Guard and Pegboard-based handlers when transient tunnel (UPS) issues occur, for both HTTP and WebSocket traffic. + +## HTTP + +- Signal: A retryable transient tunnel failure is signaled by returning an HTTP 503 with the `X-RIVET-ERROR` header set. + - Example (Pegboard Gateway): on tunnel closed (e.g., UPS `no_responders` or `request_timeout`), the gateway replies with `503` and `X-RIVET-ERROR: pegboard_gateway.tunnel_closed`. + +- Guard behavior + - Guard considers a response retryable if `status == 503` and the `X-RIVET-ERROR` header is present. + - Guard then applies exponential backoff (from middleware-config: `max_attempts`, `initial_interval`), re-resolves the route with `ignore_cache = true`, and retries the request. + - On successful retry, traffic proceeds normally to the new target. + - If attempts are exhausted, Guard returns an upstream error to the client. + +- Notes for implementers + - For transient tunnel failures, return a 503 with `X-RIVET-ERROR` to trigger Guard retries. Use an empty body or minimal payload as appropriate. + - Do not 503 for non-transient errors; let the normal error flow apply. + +## WebSocket + +This section explains how WebSocket retries are coordinated between Guard and Pegboard-based handlers. + +## Overview + +- Retries are only possible before the client WebSocket is accepted ("opening" stage). +- A retryable transient failure is signaled via the error `guard.websocket_service_unavailable` (WebSocketServiceUnavailable). +- When Guard receives this error during opening, it re-resolves routes (ignoring cache), applies backoff, and retries with the same client socket and a new handler if available. +- After the client socket is accepted ("open"), retries are not possible; the handler must close gracefully on failure. + +### Lifecycle Behavior + +- Opening (before accept) + - Source: handler detects a transient UPS/tunnel issue before awaiting the `HyperWebsocket` (e.g., failing to `ups.request(...)` to open, or failing to `ups.subscribe(...)`). + - Handler contract: + - Do not await the client websocket yet. + - Return the untouched `HyperWebsocket` in the error tuple so Guard still owns it: `Err((client_ws, err))`. + - The outer wrapper maps tunnel-closed UPS errors (e.g., `ups.no_responders`, `ups.request_timeout`) to `WebSocketServiceUnavailable`. + - Guard reaction: + - Treats `WebSocketServiceUnavailable` as retryable. + - Re-resolves the route with ignore-cache=true, using middleware-config retry/backoff. + - Outcomes: + - Re-resolve → `CustomServe`: reuse the same `client_ws` and retry with the new handler. + - Re-resolve → `Response`: accept client, send a Close with the response message as the reason. + - Re-resolve → `Target` (non-CustomServe) or mismatch: accept client, send a Close with a generic message (cannot retry). + - Attempts exhausted: accept client and send a Close with the original error message. + +- Open (after accept) + - The handler has awaited the client websocket; Guard can no longer retry. + - Any failures (UPS send/receive, serialization, etc.) should be handled by closing the connection gracefully. + +- Closing + - Best-effort signaling to the server via `ups.request(...)` and to the client via Close frames. + - Failures are ignored; no retries. + +- Closed + - No further action. + +### Implementer Guidance + +- Keep the client socket intact for retries: + - Only return a retryable error (that maps to `WebSocketServiceUnavailable`) before awaiting the client websocket. + - Return the socket in the error tuple: `Err((client_ws, err))`. + +- Map tunnel-closed errors at the wrapper: + - In the outer `handle_websocket` wrapper, detect tunnel-closed (e.g., `ups.no_responders`, `ups.request_timeout`) and map to `WebSocketServiceUnavailable`. + - `handle_websocket_inner` should return raw errors; do not construct `WebSocketServiceUnavailable` inside the inner function. + +- Use `ups.request` for all tunnel operations (open, messages, close): + - Pre-accept failures should surface as errors with the unconsumed `client_ws` so Guard can retry. + - Post-accept failures should break streams and close gracefully; do not attempt retries. + +- Backoff and attempts: + - Guard uses middleware-config values for `max_attempts` and `initial_interval` to perform exponential backoff between retries. + - Routes are re-resolved with ignore-cache=true on each retry to avoid stale targets. + +### Rationale + +- Returning the untouched `HyperWebsocket` in errors preserves the ability for Guard to re-route and retry without disconnecting the client. +- Mapping tunnel-closed conditions to a single sentinel error (`WebSocketServiceUnavailable`) provides a consistent, guard-specific signal for retryability. +- Restricting retries to pre-accept avoids protocol violations and simplifies resource ownership. diff --git a/dev-docs/SDKS.md b/dev-docs/SDKS.md new file mode 100644 index 0000000000..85ac3a5db6 --- /dev/null +++ b/dev-docs/SDKS.md @@ -0,0 +1,9 @@ +# Generating SDKs + +To make sure the openapi spec is up to date, run `cargo check -p rivet-dump-openapi` + +Use `./scripts/fern/gen.sh` to generate the SDKs, which will be outputted under `sdks/api` + +# Endpoints + +A current list of API endpoints can be found at `packages/core/api-public/src/router.rs` or in the `out/openapi.json` file. diff --git a/dev-docs/TEST_DEPENDENCIES.md b/dev-docs/TEST_DEPENDENCIES.md new file mode 100644 index 0000000000..7eb03f0f53 --- /dev/null +++ b/dev-docs/TEST_DEPENDENCIES.md @@ -0,0 +1,43 @@ +# Test Dependencies + +The `rivet-test-deps` package provides isolated test environments with configurable database and pub/sub backends. + +## Configuration + +Configure backends via environment variables: + +- `RIVET_TEST_DATABASE`: Choose database backend + - `foundationdb` - Runs FoundationDB in Docker + - `postgres` - PostgreSQL in Docker + - `filesystem` - RocksDB with temp directory (default) + +- `RIVET_TEST_PUBSUB`: Choose pub/sub backend + - `nats` - Runs NATS in Docker + - `postgres_notify` - PostgreSQL in Docker + - `memory` - In-memory channels (default) + +- `RUST_LOG`: Enable debug logs to see container lifecycle details + - For example, `RUST_LOG=debug` will enable more verbose logs + +## How It Works + +1. **Port Selection**: Automatically picks unused ports for all services +2. **Container Management**: + - Starts Docker containers for services that require them + - Each test gets unique container names using UUIDs + - Containers are automatically cleaned up on drop +3. **Config Generation**: Creates a complete Rivet config with the selected backends +4. **Isolation**: Each test instance gets isolated resources (unique channels, temp dirs, containers) + +## Usage + +```rust +let deps = TestDeps::new().await?; +// Use deps.pools() and deps.config() for your tests +// Containers are cleaned up automatically when deps is dropped +``` + +For multi-datacenter tests: +```rust +let deps = TestDeps::new_multi(&[1, 2, 3]).await?; +``` diff --git a/dev-docs/design-choicse/EMBEDDED_KV.md b/dev-docs/design-choicse/EMBEDDED_KV.md new file mode 100644 index 0000000000..74cab6e614 --- /dev/null +++ b/dev-docs/design-choicse/EMBEDDED_KV.md @@ -0,0 +1,80 @@ +# Embedded KV + +## Goals + +- Embedded (no need for multi-process) +- Similarity to FDB in transacations +- Supports high write throughput + +## Decision + +Chose RocksDB because: + +- It's stable & boring +- Supports high write throughput + +Nice to haves: + +- Better compression on disk + +## Evaluation + +### RocksDB + +Uses LSM trees. Requires backgound compaction. Has a lot of overhead to work like a "real" database. + +Pros: + +- Supports a WAL for logging & buffering writes + +Cons: + +- Significantly more complicated +- Overhead of background threads managing compaction +- Does not provide native MVCC + conflict ranges, we must re-implement this ourselves + +### LMDB + +Uses B+ tree for storage. mmaps database. + +**The critical downside of LMDB is that performance suffers under write-heavy workoads from (a) single writer locks and (b) uses mmap instead of buffering writes.** + +Pros: + +- Simple implementation +- Very little overhead + +Cons: + +- No compaction +- Single writer lock +- Transaction commits each have an fsync, while RocksDB can optimize with a WAL + batching writes +- Uses pages with mmap which is slower than using a WAL + batching writes +- Does not work well with small writes since it's copied at the page level (Rivet is almost all small writes) + +### sled, redb, fjall + +All three differe significantly, but the primary reason for disqualifying these is maturity. Sled claims to be "beta" and not mature yet, while redb and fjall claim to have a stable disk format. + +**This is not a place we need to innovate, so it makes more sense to go with an established embedded KV.** + +Pros: + +- Rust-native + - Less potential issues with building & linking + - Theoretically faster compilation than RocksDB + +### SQLite + +This would be the simplest & most straightforward option in terms of support. FDB's pre-7.0 storage engine is based on the SQLite's B-tree implementation. + +**SQLite provides overhead we don't need when options like RocksDB or LMDB exist.** + +Pros: + +- Widely supported, no issues with building it +- We already have a deep experience with SQLite + +## Resources + +- https://github.com/marvin-j97/rust-storage-bench diff --git a/docker/README.md b/docker/README.md deleted file mode 100644 index 1f3d6c34e2..0000000000 --- a/docker/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Docker Configurations - -- [server](./server/) is the production-ready Rivet server. -- [client](./client/) is the production-ready Rivet client. -- [monolith](./dev-monolith/) is for running a Rivet server & client to develop your application with in a single container. It can also be used in an external Docker Compose. -- [dev-full](./dev-full/) (Docker Compose) is for testing & developing Rivet itself. - -## netrc & GitHub - -Rivet depends on cloning a lot of repos. GitHub rate limits these pulls, so we -have to authenticate with a GitHub Token in order to successfully build these -images in GitHub Actions. - -To do this, we generate a `.netrc` file with `secrets.GITHUB_TOKEN` (see -`.github/actions/docker-setup`). This file gets mounted as a Docker secret in -the build stage. - -It's important that we don't use an `ARG` or `COPY` for the secert nor write it -to the file system, since this might expose the token in the released image. In -theory, all Docker images use a separate runner build stage from the builder -stage so we _could_ write the token to the builder filesystem to simplify -things, but this risk should be avoided in case the wrong image gets pushed or -the wrong artifact ends up in the final image. - diff --git a/docker/dev-full/README.md b/docker/dev-full/README.md deleted file mode 100644 index 61dd51b9af..0000000000 --- a/docker/dev-full/README.md +++ /dev/null @@ -1,108 +0,0 @@ -# Full Development Docker Compose - -## Operating - -Find our docs [here](https://rivet.gg/docs/self-hosting/docker-compose). - -## Development - -### Rebuilding - -To rebuild all services, run: - -```bash -docker compose -f docker/dev-full/docker-compose.yml up -d --build -``` - -To rebuild just the server, run: - -```bash -docker compose -f docker/dev-full/docker-compose.yml up -d --build rivet-server -``` - -### Logs - -To fetch logs for a service, run: - -```bash -docker compose -f docker/dev-full/docker-compose.yml logs {name} -``` - -#### Following - -To follow logs, run: - -```bash -docker compose -f docker/dev-full/docker-compose.yml logs -f {name} -``` - -#### Grep - -It's common to use grep (or the more modern -[ripgrep](https://www.google.com/search?q=ripgrep&oq=ripgrep&sourceid=chrome&ie=UTF-8)) to filter logs. - -For example, to find all errors in `rivet-server` with the 10 preceding lines, run: - -```bash -docker compose -f docker/dev-full/docker-compose.yml logs rivet-server | grep -B 10 level=error -``` - -Logs for `rivet-server` and `rivet-client` can also be configured via the environment. See [here](/docs/self-hosting/client-config) for -more information. - -## Troubleshooting - -### `Illegal instruction` during `apt-get install` on macOS - -If you see this output: - -``` -Updating certificates in /etc/ssl/certs... -Illegal instruction -Illegal instruction -dpkg: error processing package ca-certificates (--configure): - installed ca-certificates package post-installation script subprocess returned error exit status 132 -Setting up libgssapi-krb5-2:amd64 (1.20.1-2+deb12u2) ... -Setting up libcurl4:amd64 (7.88.1-10+deb12u8) ... -Setting up curl (7.88.1-10+deb12u8) ... -Processing triggers for libc-bin (2.36-9+deb12u9) ... -Errors were encountered while processing: - ca-certificates -E: Sub-process /usr/bin/dpkg returned an error code (1) -``` - -Try changing your Docker VM to _Docker VMM_. See [here](https://github.com/docker/for-mac/issues/7255#issuecomment-2567154899) for more information. - -### FoundationDB unhealthy on macOS - -If you see this output: - -``` -Configuring database... -Starting FDB server on 172.19.0.10:4500 -ERROR: Disk i/o operation failed (1510) -qemu: uncaught target signal 11 (Segmentation fault) - core dumped -/var/fdb/scripts/fdb.bash: line 68: 38 Segmentation fault fdbserver --listen-address 0.0.0.0:"$FDB_PORT" --public-address "$PUBLIC_IP:$FDB_PORT" --datadir /var/fdb/data --logdir /var/fdb/logs --locality-zoneid="$(hostname)" --locality-machineid="$(hostname)" --class "$FDB_PROCESS_CLASS" -Database already configured. -Starting FDB server on 172.19.0.10:4500 -qemu: uncaught target signal 11 (Segmentation fault) - core dumped -/var/fdb/scripts/fdb.bash: line 68: 32 Segmentation fault fdbserver --listen-address 0.0.0.0:"$FDB_PORT" --public-address "$PUBLIC_IP:$FDB_PORT" --datadir /var/fdb/data --logdir /var/fdb/logs --locality-zoneid="$(hostname)" --locality-machineid="$(hostname)" --class "$FDB_PROCESS_CLASS" -Database already configured. -Starting FDB server on 172.19.0.10:4500 -Error: Disk i/o operation failed -Database already configured. -Starting FDB server on 172.19.0.10:4500 -qemu: uncaught target signal 11 (Segmentation fault) - core dumped -/var/fdb/scripts/fdb.bash: line 68: 32 Segmentation fault fdbserver --listen-address 0.0.0.0:"$FDB_PORT" --public-address "$PUBLIC_IP:$FDB_PORT" --datadir /var/fdb/data --logdir /var/fdb/logs --locality-zoneid="$(hostname)" --locality-machineid="$(hostname)" --class "$FDB_PROCESS_CLASS" -Database already configured. -Starting FDB server on 172.19.0.10:4500 -qemu: uncaught target signal 11 (Segmentation fault) - core dumped -/var/fdb/scripts/fdb.bash: line 68: 32 Segmentation fault fdbserver --listen-address 0.0.0.0:"$FDB_PORT" --public-address "$PUBLIC_IP:$FDB_PORT" --datadir /var/fdb/data --logdir /var/fdb/logs --locality-zoneid="$(hostname)" --locality-machineid="$(hostname)" --class "$FDB_PROCESS_CLASS" -Database already configured. -Starting FDB server on 172.19.0.12:4500 -qemu: uncaught target signal 11 (Segmentation fault) - core dumped -/var/fdb/scripts/fdb.bash: line 68: 32 Segmentation fault fdbserver --listen-address 0.0.0.0:"$FDB_PORT" --public-address "$PUBLIC_IP:$FDB_PORT" --datadir /var/fdb/data --logdir /var/fdb/logs --locality-zoneid="$(hostname)" --locality-machineid="$(hostname)" --class "$FDB_PROCESS_CLASS" -``` - -Try changing you Docker VM to _Apple Virtualization framework_ with _Use Rosetta_ and _VirtioFS_ enabled. - diff --git a/docker/dev-full/clickhouse/config.xml b/docker/dev-full/clickhouse/config.xml deleted file mode 100644 index 5d716f5468..0000000000 --- a/docker/dev-full/clickhouse/config.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - localhost - 9181 - - - - - - 9181 - 1 - /var/lib/clickhouse/coordination/log - /var/lib/clickhouse/coordination/snapshots - - - 10000 - 30000 - warning - - - - - 1 - localhost - 9234 - - - - - - /clickhouse/tables/{shard}/{database}/{table} - {replica} - - - - cluster1 - replica1 - 01 - - diff --git a/docker/dev-full/clickhouse/init/01-create-otel-table.sql b/docker/dev-full/clickhouse/init/01-create-otel-table.sql deleted file mode 100644 index 812f878f85..0000000000 --- a/docker/dev-full/clickhouse/init/01-create-otel-table.sql +++ /dev/null @@ -1,2 +0,0 @@ -CREATE DATABASE IF NOT EXISTS otel; - diff --git a/docker/dev-full/clickhouse/users.xml b/docker/dev-full/clickhouse/users.xml deleted file mode 100644 index 5cc16cef4d..0000000000 --- a/docker/dev-full/clickhouse/users.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - 1 - - - default - - - default - - ::/0 - - - - default - - - 1 - 1 - 1 - - - - .* - - - - - - - - 10000000000 - 300 - 1000000000 - - - - - - - - 3600 - 0 - 0 - 0 - 0 - 0 - - - - diff --git a/docker/dev-full/docker-compose.yml b/docker/dev-full/docker-compose.yml deleted file mode 100644 index 04c6a77892..0000000000 --- a/docker/dev-full/docker-compose.yml +++ /dev/null @@ -1,436 +0,0 @@ -services: - rivet-server: - build: - context: ../.. - dockerfile: docker/universal/Dockerfile - target: server-full - platform: linux/amd64 - restart: unless-stopped - command: /usr/bin/rivet-server start - environment: - - RUST_BACKTRACE=1 - - RUST_LOG_ANSI_COLOR=1 - - RIVET_OTEL_ENABLED=1 - - RIVET_OTEL_SAMPLER_RATIO=1 - - RIVET_OTEL_ENDPOINT=http://otel-collector:4317 - - RUST_LOG=debug,hyper=info - stop_grace_period: 0s - ports: - # API - - "6420:6420" - # API edge - - "6421:6421" - # Pegboard - - "6422:6422" - depends_on: - cockroachdb: - condition: service_healthy - redis: - condition: service_healthy - clickhouse: - condition: service_healthy - nats: - condition: service_healthy - seaweedfs: - condition: service_healthy - vector-server: - condition: service_started - volumes: - - ./rivet-server/config.jsonc:/etc/rivet-server/config.jsonc:ro - networks: - - rivet-network - healthcheck: - test: ["CMD", "curl", "-f", "http://127.0.0.1:6430/health/liveness"] - interval: 2s - timeout: 10s - retries: 10 - # Initial SQL migrations sometimes take time to run - start_period: 30s - - rivet-edge-server: - build: - context: ../.. - dockerfile: docker/universal/Dockerfile - target: edge-server - platform: linux/amd64 - restart: unless-stopped - command: /usr/bin/rivet-edge-server start --skip-provision - environment: - - RUST_BACKTRACE=1 - - RUST_LOG_ANSI_COLOR=1 - - RIVET_OTEL_ENABLED=1 - - RIVET_OTEL_SAMPLER_RATIO=1 - - RIVET_SERVICE_NAME=rivet-edge - - RIVET_OTEL_ENDPOINT=http://otel-collector:4317 - - RUST_LOG=debug,hyper=info - stop_grace_period: 0s - ports: - # API - - "6423:6423" - depends_on: - rivet-server: - condition: service_healthy - cockroachdb: - condition: service_healthy - redis: - condition: service_healthy - nats: - condition: service_healthy - seaweedfs: - condition: service_healthy - vector-server: - condition: service_started - volumes: - - ./rivet-edge-server/config.jsonc:/etc/rivet-server/config.jsonc:ro - - sqlite-data:/root/.local/share/rivet-sqlite:rw - networks: - - rivet-network - healthcheck: - test: ["CMD", "curl", "-f", "http://127.0.0.1:6430/health/liveness"] - interval: 2s - timeout: 10s - retries: 10 - - rivet-shell: - build: - context: ../.. - dockerfile: docker/universal/Dockerfile - target: server-full - platform: linux/amd64 - restart: unless-stopped - command: sleep infinity - environment: - - RUST_BACKTRACE=1 - stop_grace_period: 0s - volumes: - - ./rivet-server:/etc/rivet-server:ro - networks: - - rivet-network - - rivet-edge-shell: - build: - context: ../.. - dockerfile: docker/universal/Dockerfile - target: edge-server - platform: linux/amd64 - restart: unless-stopped - command: sleep infinity - environment: - - RUST_BACKTRACE=1 - stop_grace_period: 0s - volumes: - - ./rivet-edge-server:/etc/rivet-server:ro - - sqlite-data:/root/.local/share/rivet-sqlite:rw - networks: - - rivet-network - - rivet-guard: - build: - context: ../.. - dockerfile: docker/universal/Dockerfile - target: rivet-guard - platform: linux/amd64 - restart: unless-stopped - command: /usr/bin/rivet-guard - environment: - - RUST_LOG=debug - - RUST_BACKTRACE=1 - - RUST_LOG_ANSI_COLOR=1 - - RIVET_OTEL_ENABLED=1 - - RIVET_OTEL_SAMPLER_RATIO=1 - - RIVET_SERVICE_NAME=rivet-guard - - RIVET_OTEL_ENDPOINT=http://otel-collector:4317 - - RUST_LOG=debug,hyper=info - stop_grace_period: 0s - ports: - # HTTP - - "7080:7080" - # HTTPS - - "7443:7443" - # Enable TCP & UDP port ranges. - # - # Corresponds to `server.rivet.guard.min_ingress_port_tcp` and - # `actor.network.wan_port_range_max` in `rivet-server/config.jsonc`. - # - # We only reserve 100 ports instead of the default 22,000 since each - # individual port converts to an iptable rule when using Docker, which - # can cause unexpected side effects. This limits the number of actors - # using host networking to 100. - - "7500-7599:7500-7599" - depends_on: - rivet-server: - condition: service_healthy - cockroachdb: - condition: service_healthy - redis: - condition: service_healthy - nats: - condition: service_healthy - seaweedfs: - condition: service_healthy - vector-server: - condition: service_started - volumes: - - ./rivet-guard/config.jsonc:/etc/rivet-server/config.jsonc:ro - - ./rivet-guard/tls/:/etc/rivet-server/tls/:ro - - sqlite-data:/root/.local/share/rivet-sqlite:rw - networks: - - rivet-network - - cockroachdb: - restart: unless-stopped - image: cockroachdb/cockroach:v24.2.3 - command: start-single-node --insecure - volumes: - - cockroach-data:/cockroach/cockroach-data - networks: - - rivet-network - healthcheck: - test: ["CMD", "curl", "-f", "http://127.0.0.1:8080/health?ready=1"] - interval: 2s - timeout: 10s - retries: 10 - - rivet-client: - build: - context: ../.. - dockerfile: docker/universal/Dockerfile - target: client-full - # TODO(RVT-4168): Compile libfdb from scratch for ARM - platform: linux/amd64 - restart: unless-stopped - command: -c /etc/rivet-client/config.jsonc - # entrypoint: entrypoint.sh - # Required for runc & cnitool to operate - privileged: true - environment: - - RUST_BACKTRACE=1 - - RUST_LOG_ANSI_COLOR=1 - - RIVET_OTEL_ENABLED=1 - - RIVET_OTEL_SAMPLER_RATIO=1 - - RIVET_SERVICE_NAME=rivet-client - - RIVET_OTEL_ENDPOINT=http://otel-collector:4317 - - RUST_LOG=debug,hyper=info - - __HACK__DISABLE_FETCH_IMAGE_SIZE=1 - stop_grace_period: 0s - depends_on: - # HACK: rivet-server dependency since we need to do a DNS lookup in entrypoint.sh for the iptables chain - rivet-server: - condition: service_healthy - rivet-edge-server: - condition: service_healthy - foundationdb: - condition: service_healthy - volumes: - # - ./rivet-client/entrypoint.sh:/usr/local/bin/entrypoint.sh:ro - - ./rivet-client/config.jsonc:/etc/rivet-client/config.jsonc:ro - - client-data:/var/lib/rivet-client - ports: - # Enable host networking for actors - # - # Corresponds to `actor.network.wan_port_range_min` and - # `actor.network.wan_port_range_max` in `rivet-client/config.jsonc`. - # - # We only reserve 100 ports instead of the default 22,000. See - # rivet-guard for explanation. - - "7600-7699:7600-7699" - # cAdvisor metrics endpoint - - "7780:7780" - networks: - - rivet-network - - redis: - restart: unless-stopped - image: bitnami/valkey:8.0.1 - # TODO: Remove root user - user: root - volumes: - - redis-data:/data - command: redis-server --requirepass password --save 60 1 --appendonly yes - networks: - - rivet-network - ports: - - "6379:6379" - healthcheck: - test: ["CMD", "redis-cli", "ping"] - interval: 2s - timeout: 10s - retries: 10 - - clickhouse: - restart: unless-stopped - image: clickhouse/clickhouse-server:25.1.5 - volumes: - - clickhouse-data:/var/lib/clickhouse - - ./clickhouse/config.xml:/etc/clickhouse-server/config.d/config.xml - - ./clickhouse/users.xml:/etc/clickhouse-server/users.d/users.xml - - ./clickhouse/init:/docker-entrypoint-initdb.d - environment: - # Run migrations on startup - - CLICKHOUSE_ALWAYS_RUN_INITDB_SCRIPTS=true - # Configured in users.xml - - CLICKHOUSE_USER=system - - CLICKHOUSE_PASSWORD=default - networks: - - rivet-network - ports: - - "9300:9300" - - "9301:9301" - healthcheck: - test: ["CMD", "clickhouse-client", "--password", "default", "--query", "SELECT 1"] - interval: 2s - timeout: 10s - retries: 10 - - nats: - restart: unless-stopped - image: nats:2.10.22-scratch - networks: - - rivet-network - ports: - - "4222:4222" - healthcheck: - test: ["CMD", "nats-server", "--health"] - interval: 2s - timeout: 10s - retries: 10 - - seaweedfs: - restart: unless-stopped - image: chrislusf/seaweedfs:3.79 - # TODO: Remove root user - user: root - # `raftHashicorp` speeds up initial leader election - command: | - server \ - -dir /var/lib/seaweedfs \ - -master.raftBootstrap -master.raftHashicorp \ - -s3 -s3.config /etc/seaweedfs/s3.json -s3.port=9000 -s3.allowEmptyFolder=false -s3.allowDeleteBucketNotEmpty=false - volumes: - - ./seaweedfs:/etc/seaweedfs:ro - - seaweedfs-data:/var/lib/seaweedfs - ports: - # S3 - - "9000:9000" - networks: - - rivet-network - healthcheck: - test: ["CMD", "nc", "-z", "127.0.0.1", "9000"] - interval: 2s - timeout: 10s - - foundationdb: - restart: unless-stopped - # See docs-internal/infrastructure/fdb/AVX.md - image: foundationdb/foundationdb:7.1.60 - platform: linux/amd64 - entrypoint: ["/usr/bin/tini", "-g", "--", "/usr/local/bin/entrypoint.sh"] - volumes: - - ./foundationdb/entrypoint.sh:/usr/local/bin/entrypoint.sh - - foundationdb-data:/var/fdb:rw - - foundationdb-storage-data:/var/fdb/data:rw - ports: - - "4500:4500" - healthcheck: - test: ["CMD", "fdbcli", "--exec", "status"] - interval: 2s - timeout: 10s - retries: 10 - networks: - - rivet-network - - vector-client: - restart: unless-stopped - image: timberio/vector:0.42.0-distroless-static - command: -C /etc/vector - volumes: - - ./vector-client:/etc/vector - # Mount client data to read logs - - client-data:/var/lib/rivet-client - networks: - - rivet-network - - vector-server: - restart: unless-stopped - image: timberio/vector:0.42.0-distroless-static - command: -C /etc/vector - volumes: - - vector-server-data:/var/lib/vector - - ./vector-server:/etc/vector - networks: - - rivet-network - - prometheus: - image: prom/prometheus:v2.41.0 - volumes: - - ./prometheus:/etc/prometheus - ports: - - "9090:9090" - networks: - - rivet-network - - grafana: - image: grafana/grafana:11.5.2 - volumes: - - grafana-data:/var/lib/grafana - - ./grafana/grafana.ini:/etc/grafana/grafana.ini - - ./grafana/provisioning:/etc/grafana/provisioning - - ./grafana/dashboards:/var/lib/grafana/dashboards - ports: - # 3000 is a common port, so we use 3100 instead - - "3100:3000" - networks: - - rivet-network - environment: - - GF_INSTALL_PLUGINS=grafana-clickhouse-datasource - - frontend-hub: - build: - context: ./frontend-hub - dockerfile: Dockerfile - restart: unless-stopped - working_dir: /app/frontend/apps/hub - command: /bin/bash /etc/frontend-hub/entrypoint.sh - environment: - - NODE_ENV=development - ports: - - "5080:5080" - volumes: - - ../..:/app:rw - - ./frontend-hub/entrypoint.sh:/etc/frontend-hub/entrypoint.sh:ro - networks: - - rivet-network - - otel-collector: - image: otel/opentelemetry-collector-contrib:latest - restart: unless-stopped - command: --config=/etc/otel/config.yaml - volumes: - - ./otel-collector/config.yaml:/etc/otel/config.yaml:ro - environment: - - CLICKHOUSE_PASSWORD=default - ports: - - "4317:4317" # OTLP gRPC - - "4318:4318" # OTLP HTTP - - "8888:8888" # Metrics - depends_on: - clickhouse: - condition: service_healthy - networks: - - rivet-network - -networks: - rivet-network: - driver: bridge - -volumes: - client-data: - cockroach-data: - redis-data: - clickhouse-data: - seaweedfs-data: - vector-server-data: - foundationdb-data: - foundationdb-storage-data: - sqlite-data: - grafana-data: diff --git a/docker/dev-full/foundationdb/entrypoint.sh b/docker/dev-full/foundationdb/entrypoint.sh deleted file mode 100755 index 9336a40029..0000000000 --- a/docker/dev-full/foundationdb/entrypoint.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -function configure_database() { - echo "Configuring database..." - until fdbcli --exec 'configure new single ssd' --timeout 10; do - sleep 2 - done - echo "Database configured." -} - -# Background process will wait until FoundationDB is up and configure it. -if [ ! -e /var/fdb/fdb.cluster ]; then - configure_database & -else - echo "Database already configured." -fi - -# This will automatically populate the file contents with `docker:docker@$PUBLIC_IP:$FDB_PORT` -export FDB_NETWORKING_MODE=container -exec /var/fdb/scripts/fdb.bash "$@" diff --git a/docker/dev-full/frontend-hub/Dockerfile b/docker/dev-full/frontend-hub/Dockerfile deleted file mode 100644 index ba13aba3ef..0000000000 --- a/docker/dev-full/frontend-hub/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM node:22-bullseye - -# Install corepack globally as root, then fix permissions for user 1000:1000 -RUN npm install -g corepack && \ - corepack enable && \ - chown -R 1000:1000 /usr/local/lib/node_modules/corepack* /usr/local/bin/yarn /usr/local/bin/pnpm /usr/local/bin/pnpx || true - -# Switch to user 1000:1000 -USER 1000:1000 - -# Set working directory -WORKDIR /app \ No newline at end of file diff --git a/docker/dev-full/frontend-hub/entrypoint.sh b/docker/dev-full/frontend-hub/entrypoint.sh deleted file mode 100755 index 34103d988f..0000000000 --- a/docker/dev-full/frontend-hub/entrypoint.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -e - -# Install packages -cd /app -yarn install - -# Start dev server -# -# Set base to /ui since this is where the UI is hosted in the dev server -cd /app/frontend/apps/hub -yarn dev --base=/ui diff --git a/docker/dev-full/grafana/dashboards/cache.json b/docker/dev-full/grafana/dashboards/cache.json deleted file mode 100644 index 5e9e0416ed..0000000000 --- a/docker/dev-full/grafana/dashboards/cache.json +++ /dev/null @@ -1,848 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "links": [], - "liveNow": false, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "key/s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 0 - }, - "id": 3, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(irate(rivet_cache_request_total{key=~\"[[key]]\"}[$__rate_interval])) by (key)", - "instant": false, - "legendFormat": "{{key}}", - "range": true, - "refId": "A" - } - ], - "title": "Cache Request Rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 0 - }, - "id": 4, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(rate(rivet_cache_request_error_total{key=~\"[[key]]\"}[$__rate_interval])) by (key)", - "instant": false, - "legendFormat": "{{key}}", - "range": true, - "refId": "A" - } - ], - "title": "Cache Request Error Rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "key/s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 8 - }, - "id": 1, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(irate(rivet_cache_value_miss_total{key=~\"[[key]]\"}[$__rate_interval])) by (key)", - "instant": false, - "legendFormat": "{{key}}", - "range": true, - "refId": "A" - } - ], - "title": "Cache Miss Rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "percentunit" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 8 - }, - "id": 2, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(irate(rivet_cache_value_miss_total{key=~\"[[key]]\"}[$__rate_interval]) / rate(rivet_cache_value_total{key=~\"[[key]]\"}[$__rate_interval])) by (key)", - "instant": false, - "legendFormat": "{{key}}", - "range": true, - "refId": "A" - } - ], - "title": "Cache Miss Rate (% of total)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "key/s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 16 - }, - "id": 5, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(irate(rivet_cache_value_empty_total{key=~\"[[key]]\"}[$__rate_interval])) by (key)", - "instant": false, - "legendFormat": "{{key}}", - "range": true, - "refId": "A" - } - ], - "title": "Cache Empty Rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "percentunit" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 16 - }, - "id": 6, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(irate(rivet_cache_value_empty_total{key=~\"[[key]]\"}[$__rate_interval]) / rate(rivet_cache_value_total{key=~\"[[key]]\"}[$__rate_interval])) by (key)", - "instant": false, - "legendFormat": "{{key}}", - "range": true, - "refId": "A" - } - ], - "title": "Cache Empty Rate (% of total)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "key/s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 24 - }, - "id": 7, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(irate(rivet_cache_purge_request_total{key=~\"[[key]]\"}[$__rate_interval])) by (key)", - "instant": false, - "legendFormat": "{{key}}", - "range": true, - "refId": "A" - } - ], - "title": "Cache Purge Request Rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "key/s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 24 - }, - "id": 8, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(irate(rivet_purge_cache_value_total{key=~\"[[key]]\"}[$__rate_interval])) by (key)", - "instant": false, - "legendFormat": "{{key}}", - "range": true, - "refId": "A" - } - ], - "title": "Cache Purge Rate", - "type": "timeseries" - } - ], - "refresh": "5s", - "schemaVersion": 39, - "tags": [], - "templating": { - "list": [ - { - "current": { - "selected": true, - "text": [ - "All" - ], - "value": [ - "$__all" - ] - }, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "definition": "label_values(rivet_cache_request_total,key)", - "hide": 0, - "includeAll": true, - "label": "Cache Key", - "multi": true, - "name": "key", - "options": [], - "query": { - "query": "label_values(rivet_cache_request_total,key)", - "refId": "PrometheusVariableQueryEditor-VariableQuery" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "type": "query" - } - ] - }, - "time": { - "from": "now-15m", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "Cache", - "uid": "c35233ed-b698-4838-9426-18e1586017f1", - "version": 1, - "weekStart": "" -} \ No newline at end of file diff --git a/docker/dev-full/grafana/dashboards/chirp-workflow.json b/docker/dev-full/grafana/dashboards/chirp-workflow.json deleted file mode 100644 index 332b3e7191..0000000000 --- a/docker/dev-full/grafana/dashboards/chirp-workflow.json +++ /dev/null @@ -1,2294 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 1, - "links": [], - "liveNow": false, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMax": 5, - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 0 - }, - "id": 5, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true, - "sortBy": "Last *", - "sortDesc": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum by (workflow_name) (rivet_chirp_workflow_workflow_active{workflow_name=~\"[[workflow_name]]\"})", - "instant": false, - "legendFormat": "{{workflow_name}}", - "range": true, - "refId": "A" - } - ], - "title": "Running Workflows", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMax": 5, - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 0 - }, - "id": 3, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true, - "sortBy": "Last *", - "sortDesc": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "max by (workflow_name) (rivet_chirp_workflow_workflow_sleeping{workflow_name=~\"[[workflow_name]]\"})", - "instant": false, - "legendFormat": "{{workflow_name}}", - "range": true, - "refId": "A" - } - ], - "title": "Sleeping Workflows", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMax": 5, - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 8 - }, - "id": 1, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true, - "sortBy": "Last *", - "sortDesc": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum by (workflow_name) (rivet_chirp_workflow_workflow_dead{workflow_name=~\"[[workflow_name]]\"})", - "instant": false, - "legendFormat": "{{workflow_name}}", - "range": true, - "refId": "A" - } - ], - "title": "Dead Workflows", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMax": 5, - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 8 - }, - "id": 6, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true, - "sortBy": "Last *", - "sortDesc": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum by (workflow_name, error_code) (rivet_chirp_workflow_workflow_dead{workflow_name=~\"[[workflow_name]]\"})", - "instant": false, - "legendFormat": "({{workflow_name}}) {{error_code}}", - "range": true, - "refId": "A" - } - ], - "title": "Dead Workflow Errors", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMax": 5, - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 16 - }, - "id": 2, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "sortBy": "Last *", - "sortDesc": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "count((time() - timestamp(rivet_chirp_workflow_worker_last_ping) < 30))", - "instant": false, - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Active Workers", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMax": 5, - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 16 - }, - "id": 4, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true, - "sortBy": "Last *", - "sortDesc": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum by (signal_name) (rivet_chirp_workflow_signal_pending)", - "instant": false, - "legendFormat": "{{signal_name}}", - "range": true, - "refId": "A" - } - ], - "title": "Pending Signals", - "type": "timeseries" - }, - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateOranges", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 24 - }, - "heatmap": {}, - "hideZeroBuckets": true, - "highlightCards": true, - "id": 10, - "interval": "15s", - "legend": { - "show": false - }, - "options": { - "calculate": false, - "calculation": { - "xBuckets": { - "mode": "size" - } - }, - "cellGap": 0, - "color": { - "exponent": 0.5, - "fill": "dark-orange", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "RdBu", - "steps": 64 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": true - }, - "rowsFrame": { - "layout": "auto" - }, - "tooltip": { - "mode": "single", - "showColorScale": false, - "yHistogram": true - }, - "yAxis": { - "axisPlacement": "left", - "max": "60", - "min": 0, - "reverse": false, - "unit": "s" - } - }, - "pluginVersion": "10.4.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(increase(rivet_chirp_workflow_signal_recv_lag_bucket{workflow_name=~\"[[workflow_name]]\"} [$__rate_interval])) by (le)", - "format": "heatmap", - "legendFormat": "{{le}}", - "range": true, - "refId": "A" - } - ], - "title": "Signal Receive Lag", - "tooltip": { - "show": true, - "showHistogram": true - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "s", - "logBase": 2, - "max": "60", - "min": "0", - "show": true - }, - "yBucketBound": "auto" - }, - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateOranges", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 24 - }, - "heatmap": {}, - "hideZeroBuckets": true, - "highlightCards": true, - "id": 11, - "interval": "15s", - "legend": { - "show": false - }, - "options": { - "calculate": false, - "calculation": { - "xBuckets": { - "mode": "size" - } - }, - "cellGap": 0, - "color": { - "exponent": 0.5, - "fill": "dark-orange", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "RdBu", - "steps": 64 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": true - }, - "rowsFrame": { - "layout": "auto" - }, - "tooltip": { - "mode": "single", - "showColorScale": false, - "yHistogram": true - }, - "yAxis": { - "axisPlacement": "left", - "max": "60", - "min": 0, - "reverse": false, - "unit": "s" - } - }, - "pluginVersion": "10.4.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(increase(rivet_chirp_workflow_signal_pull_duration_bucket [$__rate_interval])) by (le)", - "format": "heatmap", - "legendFormat": "{{le}}", - "range": true, - "refId": "A" - } - ], - "title": "Pull Signals Duration", - "tooltip": { - "show": true, - "showHistogram": true - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "s", - "logBase": 2, - "max": "60", - "min": "0", - "show": true - }, - "yBucketBound": "auto" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMax": 0.1, - "axisSoftMin": 0, - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 32 - }, - "id": 13, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "sortBy": "Last *", - "sortDesc": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "max by (worker_instance_id) (rivet_chirp_workflow_last_pull_workflows_duration)", - "instant": false, - "legendFormat": "{{worker_instance_id}}", - "range": true, - "refId": "A" - } - ], - "title": "Last Pull Workflows Duration", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMax": 0.1, - "axisSoftMin": 0, - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 32 - }, - "id": 14, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "sortBy": "Last *", - "sortDesc": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "max by (worker_instance_id) (rivet_chirp_workflow_last_pull_workflows_history_duration)", - "instant": false, - "legendFormat": "{{worker_instance_id}}", - "range": true, - "refId": "A" - } - ], - "title": "Last Pull Workflows History Duration", - "type": "timeseries" - }, - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateOranges", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 40 - }, - "heatmap": {}, - "hideZeroBuckets": true, - "highlightCards": true, - "id": 23, - "interval": "15s", - "legend": { - "show": false - }, - "options": { - "calculate": false, - "calculation": { - "xBuckets": { - "mode": "size" - } - }, - "cellGap": 0, - "color": { - "exponent": 0.5, - "fill": "dark-orange", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "RdBu", - "steps": 64 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": true - }, - "rowsFrame": { - "layout": "auto" - }, - "tooltip": { - "mode": "single", - "showColorScale": false, - "yHistogram": true - }, - "yAxis": { - "axisPlacement": "left", - "max": "60", - "min": 0, - "reverse": false, - "unit": "s" - } - }, - "pluginVersion": "10.4.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(increase(rivet_chirp_workflow_pull_workflows_duration_bucket [$__rate_interval])) by (le)", - "format": "heatmap", - "legendFormat": "{{le}}", - "range": true, - "refId": "A" - } - ], - "title": "Pull Workflows Duration", - "tooltip": { - "show": true, - "showHistogram": true - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "s", - "logBase": 2, - "max": "60", - "min": "0", - "show": true - }, - "yBucketBound": "auto" - }, - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateOranges", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 40 - }, - "heatmap": {}, - "hideZeroBuckets": true, - "highlightCards": true, - "id": 24, - "interval": "15s", - "legend": { - "show": false - }, - "options": { - "calculate": false, - "calculation": { - "xBuckets": { - "mode": "size" - } - }, - "cellGap": 0, - "color": { - "exponent": 0.5, - "fill": "dark-orange", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "RdBu", - "steps": 64 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": true - }, - "rowsFrame": { - "layout": "auto" - }, - "tooltip": { - "mode": "single", - "showColorScale": false, - "yHistogram": true - }, - "yAxis": { - "axisPlacement": "left", - "max": "60", - "min": 0, - "reverse": false, - "unit": "s" - } - }, - "pluginVersion": "10.4.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(increase(rivet_chirp_workflow_pull_workflows_history_duration_bucket [$__rate_interval])) by (le)", - "format": "heatmap", - "legendFormat": "{{le}}", - "range": true, - "refId": "A" - } - ], - "title": "Pull Workflows History Duration", - "tooltip": { - "show": true, - "showHistogram": true - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "s", - "logBase": 2, - "max": "60", - "min": "0", - "show": true - }, - "yBucketBound": "auto" - }, - { - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 48 - }, - "id": 16, - "panels": [], - "title": "Steps", - "type": "row" - }, - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateOranges", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 49 - }, - "heatmap": {}, - "hideZeroBuckets": true, - "highlightCards": true, - "id": 12, - "interval": "15s", - "legend": { - "show": false - }, - "options": { - "calculate": false, - "calculation": { - "xBuckets": { - "mode": "size" - } - }, - "cellGap": 0, - "color": { - "exponent": 0.5, - "fill": "dark-orange", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "RdBu", - "steps": 64 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": true - }, - "rowsFrame": { - "layout": "auto" - }, - "tooltip": { - "mode": "single", - "showColorScale": false, - "yHistogram": true - }, - "yAxis": { - "axisPlacement": "left", - "max": "60", - "min": 0, - "reverse": false, - "unit": "s" - } - }, - "pluginVersion": "10.4.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(increase(rivet_chirp_workflow_activity_duration_bucket{workflow_name=~\"[[workflow_name]]\"} [$__rate_interval])) by (le)", - "format": "heatmap", - "legendFormat": "{{le}}", - "range": true, - "refId": "A" - } - ], - "title": "Activity Duration", - "tooltip": { - "show": true, - "showHistogram": true - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "s", - "logBase": 2, - "max": "60", - "min": "0", - "show": true - }, - "yBucketBound": "auto" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "reqps" - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 49 - }, - "id": 9, - "interval": "15s", - "options": { - "legend": { - "calcs": [ - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true, - "sortBy": "Mean", - "sortDesc": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(rate(rivet_chirp_workflow_activity_errors{workflow_name=~\"[[workflow_name]]\"}[$__rate_interval])) by (activity_name, error_code)", - "legendFormat": "{{activity_name}}: {{error_code}}", - "range": true, - "refId": "A" - } - ], - "title": "Activity Error Rate", - "type": "timeseries" - }, - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateOranges", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 58 - }, - "heatmap": {}, - "hideZeroBuckets": true, - "highlightCards": true, - "id": 21, - "interval": "15s", - "legend": { - "show": false - }, - "options": { - "calculate": false, - "calculation": { - "xBuckets": { - "mode": "size" - } - }, - "cellGap": 0, - "color": { - "exponent": 0.5, - "fill": "dark-orange", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "RdBu", - "steps": 64 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": true - }, - "rowsFrame": { - "layout": "auto" - }, - "tooltip": { - "mode": "single", - "showColorScale": false, - "yHistogram": true - }, - "yAxis": { - "axisPlacement": "left", - "max": "60", - "min": 0, - "reverse": false, - "unit": "s" - } - }, - "pluginVersion": "10.4.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(increase(rivet_chirp_workflow_loop_iteration_duration_bucket{workflow_name=~\"[[workflow_name]]\"} [$__rate_interval])) by (le)", - "format": "heatmap", - "legendFormat": "{{le}}", - "range": true, - "refId": "A" - } - ], - "title": "Loop Iteration Duration", - "tooltip": { - "show": true, - "showHistogram": true - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "s", - "logBase": 2, - "max": "60", - "min": "0", - "show": true - }, - "yBucketBound": "auto" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ev/s" - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 58 - }, - "id": 25, - "interval": "15s", - "options": { - "legend": { - "calcs": [ - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true, - "sortBy": "Mean", - "sortDesc": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(irate(rivet_chirp_workflow_loop_iteration_duration_count{workflow_name=~\"[[workflow_name]]\"} [$__rate_interval])) by (workflow_name)", - "legendFormat": "{{workflow_name}}", - "range": true, - "refId": "A" - } - ], - "title": "Loop Events Per Second", - "type": "timeseries" - }, - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateOranges", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 67 - }, - "heatmap": {}, - "hideZeroBuckets": true, - "highlightCards": true, - "id": 17, - "interval": "15s", - "legend": { - "show": false - }, - "options": { - "calculate": false, - "calculation": { - "xBuckets": { - "mode": "size" - } - }, - "cellGap": 0, - "color": { - "exponent": 0.5, - "fill": "dark-orange", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "RdBu", - "steps": 64 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": true - }, - "rowsFrame": { - "layout": "auto" - }, - "tooltip": { - "mode": "single", - "showColorScale": false, - "yHistogram": true - }, - "yAxis": { - "axisPlacement": "left", - "max": "60", - "min": 0, - "reverse": false, - "unit": "s" - } - }, - "pluginVersion": "10.4.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(increase(rivet_chirp_workflow_message_send_duration_bucket{workflow_name=~\"[[workflow_name]]\"} [$__rate_interval])) by (le)", - "format": "heatmap", - "legendFormat": "{{le}}", - "range": true, - "refId": "A" - } - ], - "title": "Message Send Duration", - "tooltip": { - "show": true, - "showHistogram": true - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "s", - "logBase": 2, - "max": "60", - "min": "0", - "show": true - }, - "yBucketBound": "auto" - }, - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateOranges", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 67 - }, - "heatmap": {}, - "hideZeroBuckets": true, - "highlightCards": true, - "id": 20, - "interval": "15s", - "legend": { - "show": false - }, - "options": { - "calculate": false, - "calculation": { - "xBuckets": { - "mode": "size" - } - }, - "cellGap": 0, - "color": { - "exponent": 0.5, - "fill": "dark-orange", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "RdBu", - "steps": 64 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": true - }, - "rowsFrame": { - "layout": "auto" - }, - "tooltip": { - "mode": "single", - "showColorScale": false, - "yHistogram": true - }, - "yAxis": { - "axisPlacement": "left", - "max": "60", - "min": 0, - "reverse": false, - "unit": "s" - } - }, - "pluginVersion": "10.4.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(increase(rivet_chirp_workflow_signal_send_duration_bucket{workflow_name=~\"[[workflow_name]]\"} [$__rate_interval])) by (le)", - "format": "heatmap", - "legendFormat": "{{le}}", - "range": true, - "refId": "A" - } - ], - "title": "Signal Send Duration", - "tooltip": { - "show": true, - "showHistogram": true - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "s", - "logBase": 2, - "max": "60", - "min": "0", - "show": true - }, - "yBucketBound": "auto" - }, - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateOranges", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 76 - }, - "heatmap": {}, - "hideZeroBuckets": true, - "highlightCards": true, - "id": 22, - "interval": "15s", - "legend": { - "show": false - }, - "options": { - "calculate": false, - "calculation": { - "xBuckets": { - "mode": "size" - } - }, - "cellGap": 0, - "color": { - "exponent": 0.5, - "fill": "dark-orange", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "RdBu", - "steps": 64 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": true - }, - "rowsFrame": { - "layout": "auto" - }, - "tooltip": { - "mode": "single", - "showColorScale": false, - "yHistogram": true - }, - "yAxis": { - "axisPlacement": "left", - "max": "60", - "min": 0, - "reverse": false, - "unit": "s" - } - }, - "pluginVersion": "10.4.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(increase(rivet_chirp_workflow_find_workflows_duration_bucket{workflow_name=~\"[[workflow_name]]\"} [$__rate_interval])) by (le)", - "format": "heatmap", - "legendFormat": "{{le}}", - "range": true, - "refId": "A" - } - ], - "title": "Find Workflows Duration", - "tooltip": { - "show": true, - "showHistogram": true - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "s", - "logBase": 2, - "max": "60", - "min": "0", - "show": true - }, - "yBucketBound": "auto" - }, - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateOranges", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 76 - }, - "heatmap": {}, - "hideZeroBuckets": true, - "highlightCards": true, - "id": 19, - "interval": "15s", - "legend": { - "show": false - }, - "options": { - "calculate": false, - "calculation": { - "xBuckets": { - "mode": "size" - } - }, - "cellGap": 0, - "color": { - "exponent": 0.5, - "fill": "dark-orange", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "RdBu", - "steps": 64 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": true - }, - "rowsFrame": { - "layout": "auto" - }, - "tooltip": { - "mode": "single", - "showColorScale": false, - "yHistogram": true - }, - "yAxis": { - "axisPlacement": "left", - "max": "60", - "min": 0, - "reverse": false, - "unit": "s" - } - }, - "pluginVersion": "10.4.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(increase(rivet_chirp_workflow_workflow_dispatch_duration_bucket{workflow_name=~\"[[workflow_name]]\"} [$__rate_interval])) by (le)", - "format": "heatmap", - "legendFormat": "{{le}}", - "range": true, - "refId": "A" - } - ], - "title": "Sub Workflow Dispatch Duration", - "tooltip": { - "show": true, - "showHistogram": true - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "s", - "logBase": 2, - "max": "60", - "min": "0", - "show": true - }, - "yBucketBound": "auto" - } - ], - "refresh": "5s", - "schemaVersion": 39, - "tags": [ - "chirp" - ], - "templating": { - "list": [ - { - "current": { - "selected": true, - "text": [ - "All" - ], - "value": [ - "$__all" - ] - }, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "definition": "label_values(rivet_chirp_workflow_workflow_total,workflow_name)", - "hide": 0, - "includeAll": true, - "label": "Workflow Name", - "multi": true, - "name": "workflow_name", - "options": [], - "query": { - "qryType": 1, - "query": "label_values(rivet_chirp_workflow_workflow_total,workflow_name)", - "refId": "PrometheusVariableQueryEditor-VariableQuery" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "type": "query" - } - ] - }, - "time": { - "from": "now-5m", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "Chirp / Workflow", - "uid": "636d22f9-d18f-4086-8b45-7c50886a105c", - "version": 1, - "weekStart": "" -} \ No newline at end of file diff --git a/docker/dev-full/grafana/dashboards/futures.json b/docker/dev-full/grafana/dashboards/futures.json deleted file mode 100644 index dc16092490..0000000000 --- a/docker/dev-full/grafana/dashboards/futures.json +++ /dev/null @@ -1,177 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "links": [], - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 0 - }, - "id": 1, - "interval": "15s", - "options": { - "calculate": false, - "calculation": { - "xBuckets": { - "mode": "size" - } - }, - "cellGap": 0, - "color": { - "exponent": 0.5, - "fill": "dark-orange", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "RdBu", - "steps": 64 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": true - }, - "rowsFrame": { - "layout": "auto" - }, - "tooltip": { - "mode": "single", - "showColorScale": false, - "yHistogram": true - }, - "yAxis": { - "axisPlacement": "left", - "max": "60", - "min": 0, - "reverse": false, - "unit": "s" - } - }, - "pluginVersion": "11.5.2", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(increase(rivet_instrumented_future_duration_bucket{name=~\"[[name]]\", location=~\"[[location]]\"} [$__rate_interval])) by (le)", - "format": "heatmap", - "legendFormat": "{{le}}", - "range": true, - "refId": "A" - } - ], - "title": "Instrumented Future Duration", - "type": "heatmap" - } - ], - "preload": false, - "refresh": "30s", - "schemaVersion": 40, - "tags": [], - "templating": { - "list": [ - { - "current": { - "text": [ - "All" - ], - "value": [ - "$__all" - ] - }, - "definition": "label_values(rivet_instrumented_future_duration_count,name)", - "includeAll": true, - "label": "Name", - "multi": true, - "name": "name", - "options": [], - "query": { - "qryType": 1, - "query": "label_values(rivet_instrumented_future_duration_count,name)", - "refId": "PrometheusVariableQueryEditor-VariableQuery" - }, - "refresh": 1, - "regex": "", - "type": "query" - }, - { - "current": { - "text": [ - "All" - ], - "value": [ - "$__all" - ] - }, - "definition": "label_values(rivet_instrumented_future_duration_count,location)", - "includeAll": true, - "label": "Location", - "multi": true, - "name": "location", - "options": [], - "query": { - "qryType": 1, - "query": "label_values(rivet_instrumented_future_duration_count,location)", - "refId": "PrometheusVariableQueryEditor-VariableQuery" - }, - "refresh": 1, - "regex": "", - "type": "query" - } - ] - }, - "time": { - "from": "now-15m", - "to": "now" - }, - "timepicker": {}, - "timezone": "browser", - "title": "Futures", - "version": 0, - "weekStart": "" -} \ No newline at end of file diff --git a/docker/dev-full/grafana/dashboards/rivet-sqlite.json b/docker/dev-full/grafana/dashboards/rivet-sqlite.json deleted file mode 100644 index 54ae4f0bc8..0000000000 --- a/docker/dev-full/grafana/dashboards/rivet-sqlite.json +++ /dev/null @@ -1,992 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "links": [], - "panels": [ - { - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 15, - "panels": [], - "title": "Overview", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "none" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 1 - }, - "id": 14, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(max_over_time(rivet_sqlite_pool_conn_size{cluster_id=~\"[[cluster_id]]\", datacenter_id=~\"[[datacenter_id]]\"}[$__interval])) by (cluster_id, datacenter_id, server_id, pool_type, conn_type)", - "instant": false, - "legendFormat": "{{cluster_id}} {{datacenter_id}} {{server_id}} {{pool_type}} {{conn_type}}", - "range": true, - "refId": "A" - } - ], - "title": "Pool Connections", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "none" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 1 - }, - "id": 21, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(max_over_time(rivet_sqlite_large_db{cluster_id=~\"[[cluster_id]]\", datacenter_id=~\"[[datacenter_id]]\"}[$__interval])) by (cluster_id, datacenter_id, server_id, pool_type, key)", - "instant": false, - "legendFormat": "{{cluster_id}} {{datacenter_id}} {{server_id}} {{pool_type}} {{key}}", - "range": true, - "refId": "A" - } - ], - "title": "Large Pools", - "type": "timeseries" - }, - { - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 9 - }, - "id": 20, - "panels": [], - "title": "Get Pool", - "type": "row" - }, - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateOranges", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 6, - "y": 10 - }, - "heatmap": {}, - "hideZeroBuckets": true, - "highlightCards": true, - "id": 16, - "legend": { - "show": false - }, - "options": { - "calculate": false, - "calculation": { - "xBuckets": { - "mode": "size" - } - }, - "cellGap": 0, - "color": { - "exponent": 0.5, - "fill": "dark-orange", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "RdBu", - "steps": 64 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": true - }, - "rowsFrame": { - "layout": "auto" - }, - "tooltip": { - "mode": "single", - "showColorScale": false, - "yHistogram": true - }, - "yAxis": { - "axisPlacement": "left", - "max": "60", - "min": 0, - "reverse": false, - "unit": "s" - } - }, - "pluginVersion": "10.4.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(increase(rivet_sqlite_get_pool_duration_bucket{cluster_id=~\"[[cluster_id]]\", datacenter_id=~\"[[datacenter_id]]\"} [$__rate_interval])) by (le)", - "format": "heatmap", - "legendFormat": "{{le}}", - "range": true, - "refId": "A" - } - ], - "title": "Duration", - "tooltip": { - "show": true, - "showHistogram": true - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "s", - "logBase": 2, - "max": "60", - "min": "0", - "show": true - }, - "yBucketBound": "auto" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 8, - "x": 0, - "y": 19 - }, - "id": 17, - "interval": "15s", - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "10.1.4", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(rate(rivet_sqlite_get_pool_duration_sum{cluster_id=~\"[[cluster_id]]\", datacenter_id=~\"[[datacenter_id]]\"} [$__rate_interval])) by (cluster_id, datacenter_id, server_id, pool_type, conn_type, did_insert)\r\n/\r\nsum(rate(rivet_sqlite_get_pool_duration_count{cluster_id=~\"[[cluster_id]]\", datacenter_id=~\"[[datacenter_id]]\"} [$__rate_interval])) by (cluster_id, datacenter_id, server_id, pool_type, conn_type, did_insert)", - "format": "heatmap", - "legendFormat": "{{cluster_id}} {{datacenter_id}} {{server_id}} {{pool_type}} {{conn_type}} {{did_insert}}", - "range": true, - "refId": "A" - } - ], - "title": "Duration (avg)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 8, - "x": 8, - "y": 19 - }, - "id": 18, - "interval": "15s", - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "10.1.4", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, \r\n sum(rate(rivet_sqlite_get_pool_duration_bucket{cluster_id=~\"[[cluster_id]]\", datacenter_id=~\"[[datacenter_id]]\"} [$__rate_interval]))\r\n by (le, cluster_id, datacenter_id, server_id, pool_type, conn_type, did_insert)\r\n)", - "format": "heatmap", - "legendFormat": "{{cluster_id}} {{datacenter_id}} {{server_id}} {{pool_type}} {{conn_type}} {{did_insert}}", - "range": true, - "refId": "A" - } - ], - "title": "Duration (p95)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 8, - "x": 16, - "y": 19 - }, - "id": 19, - "interval": "15s", - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "10.1.4", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.99, \r\n sum(rate(rivet_sqlite_get_pool_duration_bucket{cluster_id=~\"[[cluster_id]]\", datacenter_id=~\"[[datacenter_id]]\"} [$__rate_interval]))\r\n by (le, cluster_id, datacenter_id, server_id, pool_type, conn_type, did_insert)\r\n)", - "format": "heatmap", - "legendFormat": "{{cluster_id}} {{datacenter_id}} {{server_id}} {{pool_type}} {{conn_type}} {{did_insert}}", - "range": true, - "refId": "A" - } - ], - "title": "Duration (p99)", - "type": "timeseries" - }, - { - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 28 - }, - "id": 22, - "panels": [], - "title": "FDB", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "binBps" - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 8, - "x": 0, - "y": 29 - }, - "id": 23, - "interval": "15s", - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "10.1.4", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "avg by(datacenter_id) (rivet_sqlite_upload_db_rate)", - "format": "heatmap", - "legendFormat": "{{cluster_id}} {{datacenter_id}} {{server_id}} {{pool_type}} {{conn_type}} {{did_insert}}", - "range": true, - "refId": "A" - } - ], - "title": "FDB Upload Rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "binBps" - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 8, - "x": 8, - "y": 29 - }, - "id": 24, - "interval": "15s", - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "10.1.4", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "avg by(datacenter_id) (rivet_sqlite_download_db_rate)", - "format": "heatmap", - "legendFormat": "{{cluster_id}} {{datacenter_id}} {{server_id}} {{pool_type}} {{conn_type}} {{did_insert}}", - "range": true, - "refId": "A" - } - ], - "title": "FDB Download Rate", - "type": "timeseries" - } - ], - "refresh": "", - "schemaVersion": 39, - "tags": [ - "rivet" - ], - "templating": { - "list": [ - { - "current": { - "selected": true, - "text": [ - "00000000-0000-0000-0000-000000000000" - ], - "value": [ - "00000000-0000-0000-0000-000000000000" - ] - }, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "definition": "label_values(fdb_database_available,cluster_id)", - "hide": 0, - "includeAll": true, - "label": "Cluster ID", - "multi": true, - "name": "cluster_id", - "options": [], - "query": { - "qryType": 1, - "query": "label_values(fdb_database_available,cluster_id)", - "refId": "PrometheusVariableQueryEditor-VariableQuery" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "type": "query" - }, - { - "current": { - "selected": true, - "text": [ - "All" - ], - "value": [ - "$__all" - ] - }, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "definition": "label_values(fdb_database_available,datacenter_id)", - "hide": 0, - "includeAll": true, - "label": "Datacenter ID", - "multi": true, - "name": "datacenter_id", - "options": [], - "query": { - "qryType": 1, - "query": "label_values(fdb_database_available,datacenter_id)", - "refId": "PrometheusVariableQueryEditor-VariableQuery" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "type": "query" - }, - { - "current": { - "selected": true, - "text": [ - "All" - ], - "value": [ - "$__all" - ] - }, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "definition": "label_values(fdb_database_available,server_id)", - "hide": 0, - "includeAll": true, - "label": "Server ID", - "multi": true, - "name": "server_id", - "options": [], - "query": { - "qryType": 1, - "query": "label_values(fdb_database_available,server_id)", - "refId": "PrometheusVariableQueryEditor-VariableQuery" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "type": "query" - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": {}, - "timezone": "utc", - "title": "Rivet / SQLite", - "uid": "fef9df6xdo1s0c", - "version": 7, - "weekStart": "" -} \ No newline at end of file diff --git a/docker/dev-full/grafana/dashboards/tokio.json b/docker/dev-full/grafana/dashboards/tokio.json deleted file mode 100644 index b6f4e3c35f..0000000000 --- a/docker/dev-full/grafana/dashboards/tokio.json +++ /dev/null @@ -1,663 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 1, - "id": 14, - "links": [], - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMax": 0.1, - "axisSoftMin": 0, - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 0 - }, - "id": 24, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "sortBy": "Last *", - "sortDesc": true - }, - "tooltip": { - "hideZeros": false, - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.5.2", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "rivet_tokio_global_queue_depth", - "instant": false, - "legendFormat": "{{service}}", - "range": true, - "refId": "A" - } - ], - "title": "Global Queue Depth", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMax": 0.1, - "axisSoftMin": 0, - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 0 - }, - "id": 27, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "sortBy": "Last *", - "sortDesc": true - }, - "tooltip": { - "hideZeros": false, - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.5.2", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "rivet_tokio_worker_local_queue_depth", - "instant": false, - "legendFormat": "{{service}} {{worker}}", - "range": true, - "refId": "A" - } - ], - "title": "Worker Queue Depth", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 8 - }, - "id": 11, - "interval": "15s", - "options": { - "calculate": false, - "calculation": { - "xBuckets": { - "mode": "size" - } - }, - "cellGap": 0, - "color": { - "exponent": 0.5, - "fill": "dark-orange", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "RdBu", - "steps": 64 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": true - }, - "rowsFrame": { - "layout": "auto" - }, - "tooltip": { - "mode": "single", - "showColorScale": false, - "yHistogram": true - }, - "yAxis": { - "axisPlacement": "left", - "max": "60", - "min": 0, - "reverse": false, - "unit": "s" - } - }, - "pluginVersion": "11.5.2", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(increase(rivet_tokio_task_poll_duration_bucket [$__rate_interval])) by (le)", - "format": "heatmap", - "legendFormat": "{{le}}", - "range": true, - "refId": "A" - } - ], - "title": "Task Poll Times", - "type": "heatmap" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMax": 0.1, - "axisSoftMin": 0, - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 8 - }, - "id": 26, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "sortBy": "Last *", - "sortDesc": true - }, - "tooltip": { - "hideZeros": false, - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.5.2", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "rivet_tokio_worker_overflow_count", - "instant": false, - "legendFormat": "{{service}} {{worker}}", - "range": true, - "refId": "A" - } - ], - "title": "Worker Overflow Count", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 16 - }, - "id": 23, - "interval": "15s", - "options": { - "calculate": false, - "calculation": { - "xBuckets": { - "mode": "size" - } - }, - "cellGap": 0, - "color": { - "exponent": 0.5, - "fill": "dark-orange", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "RdBu", - "steps": 64 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": true - }, - "rowsFrame": { - "layout": "auto" - }, - "tooltip": { - "mode": "single", - "showColorScale": false, - "yHistogram": true - }, - "yAxis": { - "axisPlacement": "left", - "max": "60", - "min": 0, - "reverse": false, - "unit": "s" - } - }, - "pluginVersion": "11.5.2", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(increase(rivet_future_schedule_duration_bucket [$__rate_interval])) by (le)", - "format": "heatmap", - "legendFormat": "{{le}}", - "range": true, - "refId": "A" - } - ], - "title": "Future Schedule Duration", - "type": "heatmap" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMax": 0.1, - "axisSoftMin": 0, - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 16 - }, - "id": 25, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "sortBy": "Last *", - "sortDesc": true - }, - "tooltip": { - "hideZeros": false, - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.5.2", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "rivet_tokio_thread_count", - "instant": false, - "legendFormat": "{{service}}", - "range": true, - "refId": "A" - } - ], - "title": "Thread Count", - "type": "timeseries" - } - ], - "preload": false, - "refresh": "5s", - "schemaVersion": 40, - "tags": [ - "chirp" - ], - "templating": { - "list": [ - { - "current": { - "text": "All", - "value": [ - "$__all" - ] - }, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "definition": "label_values(rivet_chirp_workflow_workflow_total,workflow_name)", - "includeAll": true, - "label": "Workflow Name", - "multi": true, - "name": "workflow_name", - "options": [], - "query": { - "qryType": 1, - "query": "label_values(rivet_chirp_workflow_workflow_total,workflow_name)", - "refId": "PrometheusVariableQueryEditor-VariableQuery" - }, - "refresh": 1, - "regex": "", - "type": "query" - } - ] - }, - "time": { - "from": "now-5m", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "Tokio", - "uid": "636d22f9-d18f-4086-8b45-7c50886a105d", - "version": 3, - "weekStart": "" -} \ No newline at end of file diff --git a/docker/dev-full/grafana/dashboards/traces.json b/docker/dev-full/grafana/dashboards/traces.json deleted file mode 100644 index c4c2c5a62f..0000000000 --- a/docker/dev-full/grafana/dashboards/traces.json +++ /dev/null @@ -1,979 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 21, - "links": [], - "panels": [ - { - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 9, - "panels": [], - "title": "Traces", - "type": "row" - }, - { - "datasource": { - "type": "grafana-clickhouse-datasource", - "uid": "clickhouse" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "bars", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 0, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 1 - }, - "id": 2, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "multi", - "sort": "desc" - } - }, - "pluginVersion": "11.5.2", - "targets": [ - { - "datasource": { - "type": "grafana-clickhouse-datasource", - "uid": "clickhouse-traces" - }, - "editorType": "sql", - "format": 0, - "meta": { - "builderOptions": { - "aggregates": [ - { - "aggregateType": "count", - "column": "" - } - ], - "columns": [ - { - "hint": "time", - "name": "Timestamp", - "type": "DateTime64(9)" - } - ], - "database": "otel", - "filters": [ - { - "condition": "AND", - "filterType": "custom", - "hint": "time", - "key": "Timestamp", - "operator": "WITH IN DASHBOARD TIME RANGE", - "restrictToFields": [ - { - "label": "Timestamp", - "name": "Timestamp", - "picklistValues": [], - "type": "DateTime64(9)" - } - ], - "type": "datetime" - } - ], - "groupBy": [ - "ServiceName" - ], - "limit": 10000, - "mode": "trend", - "orderBy": [], - "queryType": "timeseries", - "table": "otel_traces" - } - }, - "pluginVersion": "4.0.6", - "queryType": "timeseries", - "rawSql": "SELECT\r\n $__timeInterval(Timestamp) as time,\r\n ServiceName,\r\n count() as ` `\r\nFROM otel.otel_traces\r\nWHERE\r\n ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )\r\n AND ServiceName IN (${service_name:singlequote})\r\n AND SpanName IN (${span_name:singlequote})\r\n AND (($ray_id, NULL).1 = 'All' ? true : SpanAttributes['ray_id'] IN (${ray_id:singlequote}))\r\n AND (($workflow_id, NULL).1 = 'All' ? true : SpanAttributes['workflow_id'] IN (${workflow_id:singlequote}))\r\nGROUP BY ServiceName, time\r\nORDER BY time ASC\r\nLIMIT 100000\r\n", - "refId": "A" - } - ], - "title": "Traces per Service", - "type": "timeseries" - }, - { - "datasource": { - "type": "grafana-clickhouse-datasource", - "uid": "clickhouse" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Trace ID" - }, - "properties": [ - { - "id": "custom.width", - "value": 77 - }, - { - "id": "links", - "value": [ - { - "title": "__value.raw", - "url": "/d/8klBUGfVk/otel-traces?${__url_time_range}&${service_name:queryparam}&var-trace_id=${__value.raw}" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Service Name" - }, - "properties": [ - { - "id": "custom.width", - "value": 130 - }, - { - "id": "links", - "value": [ - { - "title": "__value.raw", - "url": "/d/8klBUGfVk/otel-traces?${__url_time_range}&${trace_id:queryparam}&var-serviceName=${__value.raw}" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Duration" - }, - "properties": [ - { - "id": "unit", - "value": "ms" - }, - { - "id": "custom.cellOptions", - "value": { - "mode": "lcd", - "type": "gauge", - "valueDisplayMode": "text" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "timestamp" - }, - "properties": [ - { - "id": "custom.width", - "value": 216 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Service Tags" - }, - "properties": [ - { - "id": "custom.inspect", - "value": true - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "timestamp" - }, - "properties": [ - { - "id": "custom.width", - "value": 248 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "timestamp" - }, - "properties": [ - { - "id": "custom.width", - "value": 234 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": " " - }, - "properties": [ - { - "id": "custom.width", - "value": 49 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Span Name" - }, - "properties": [ - { - "id": "custom.width", - "value": 140 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Ts" - }, - "properties": [ - { - "id": "custom.width", - "value": 168 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "URI/workflow_id/actor_id" - }, - "properties": [ - { - "id": "custom.width", - "value": 920 - } - ] - } - ] - }, - "gridPos": { - "h": 13, - "w": 24, - "x": 0, - "y": 10 - }, - "id": 4, - "options": { - "cellHeight": "sm", - "footer": { - "countRows": false, - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": true, - "displayName": "Duration" - } - ] - }, - "pluginVersion": "11.5.2", - "targets": [ - { - "datasource": { - "type": "grafana-clickhouse-datasource", - "uid": "clickhouse" - }, - "editorType": "sql", - "format": 1, - "meta": { - "builderOptions": { - "columns": [], - "database": "otel", - "filters": [ - { - "condition": "AND", - "filterType": "custom", - "key": "Timestamp", - "operator": "WITH IN DASHBOARD TIME RANGE", - "restrictToFields": [ - { - "label": "Timestamp", - "name": "Timestamp", - "picklistValues": [], - "type": "DateTime64(9)" - } - ], - "type": "datetime" - } - ], - "limit": 100, - "mode": "list", - "orderBy": [], - "queryType": "table", - "table": "otel_traces" - } - }, - "pluginVersion": "4.9.0", - "queryType": "table", - "rawSql": "SELECT\r\n (argMin(StatusCode, Timestamp) = 'Error' ? '⚠️' : '') as ` `,\r\n min(Timestamp) as Ts,\r\n TraceId as `Trace ID`,\r\n argMin(ServiceName, Timestamp) as `Service Name`,\r\n argMin(SpanName, Timestamp) as `Span Name`,\r\n argMin(coalesce(NULLIF(SpanAttributes['uri'], ''), NULLIF(SpanAttributes['workflow_id'], ''), SpanAttributes['actor_id']), Timestamp) as `URI/workflow_id/actor_id`,\r\n divide(max(Duration), 1000000) as Duration\r\nFROM otel.otel_traces\r\nWHERE\r\n ServiceName IN (${service_name:singlequote})\r\n AND SpanName IN (${span_name:singlequote})\r\n AND (($ray_id, NULL).1 = 'All' ? true : SpanAttributes['ray_id'] IN (${ray_id:singlequote}))\r\n AND (($workflow_id, NULL).1 = 'All' ? true : SpanAttributes['workflow_id'] IN (${workflow_id:singlequote}))\r\n AND ServiceName != 'loadgenerator'\r\n AND ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )\r\nGROUP BY TraceId\r\nORDER BY Duration DESC\r\nLIMIT 100\r\n", - "refId": "A" - } - ], - "title": "Traces", - "type": "table" - }, - { - "datasource": { - "type": "grafana-clickhouse-datasource", - "uid": "clickhouse" - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - }, - "gridPos": { - "h": 17, - "w": 24, - "x": 0, - "y": 23 - }, - "id": 6, - "options": { - "spanFilters": { - "criticalPathOnly": false, - "matchesOnly": false, - "serviceNameOperator": "=", - "spanNameOperator": "=" - } - }, - "pluginVersion": "11.5.2", - "targets": [ - { - "builderOptions": { - "columns": [ - { - "hint": "trace_id", - "name": "TraceId" - }, - { - "hint": "trace_span_id", - "name": "SpanId" - }, - { - "hint": "trace_parent_span_id", - "name": "ParentSpanId" - }, - { - "hint": "trace_service_name", - "name": "ServiceName" - }, - { - "hint": "trace_operation_name", - "name": "SpanName" - }, - { - "hint": "time", - "name": "Timestamp" - }, - { - "hint": "trace_duration_time", - "name": "Duration" - }, - { - "hint": "trace_tags", - "name": "SpanAttributes" - }, - { - "hint": "trace_service_tags", - "name": "ResourceAttributes" - }, - { - "hint": "trace_status_code", - "name": "StatusCode" - } - ], - "database": "otel", - "filters": [ - { - "condition": "AND", - "filterType": "custom", - "hint": "time", - "key": "", - "operator": "WITH IN DASHBOARD TIME RANGE", - "type": "datetime" - }, - { - "condition": "AND", - "filterType": "custom", - "hint": "trace_duration_time", - "key": "", - "operator": ">", - "type": "UInt64", - "value": 0 - }, - { - "condition": "AND", - "filterType": "custom", - "hint": "trace_service_name", - "key": "", - "operator": "IS ANYTHING", - "type": "string", - "value": "" - } - ], - "limit": 1000, - "meta": { - "isTraceIdMode": true, - "otelEnabled": true, - "otelVersion": "latest", - "traceDurationUnit": "nanoseconds", - "traceId": "${trace_id}" - }, - "mode": "list", - "orderBy": [ - { - "default": true, - "dir": "DESC", - "hint": "time", - "name": "" - }, - { - "default": true, - "dir": "DESC", - "hint": "trace_duration_time", - "name": "" - } - ], - "queryType": "traces", - "table": "otel_traces" - }, - "datasource": { - "type": "grafana-clickhouse-datasource", - "uid": "clickhouse-traces" - }, - "editorType": "builder", - "format": 3, - "meta": { - "builderOptions": { - "columns": [], - "database": "", - "limit": 100, - "mode": "list", - "queryType": "table", - "table": "" - } - }, - "pluginVersion": "4.0.6", - "queryType": "traces", - "rawSql": "WITH\n\t'${trace_id}' as trace_id,\n\t(SELECT min(Start) FROM otel.otel_traces_trace_id_ts WHERE TraceId = trace_id) as trace_start,\n\t(SELECT max(End) + 1 FROM otel.otel_traces_trace_id_ts WHERE TraceId = trace_id) as trace_end\nSELECT\n\tTraceId as traceID,\n\tSpanId as spanID,\n\tParentSpanId as parentSpanID,\n\tServiceName as serviceName,\n\tSpanName as operationName, Timestamp as startTime,\n\tmultiply(Duration, 0.000001) as duration,\n\tarrayMap(key -> map('key', key, 'value', SpanAttributes[key]), mapKeys(SpanAttributes)) as tags,\n\tarrayMap(key -> map('key', key, 'value', ResourceAttributes[key]), mapKeys(ResourceAttributes)) as serviceTags,\n\tarrayMap((name, timestamp, attributes) -> tuple(name, toString(multiply(toUnixTimestamp64Nano(timestamp), 0.000001)), arrayMap( key -> map('key', key, 'value', attributes[key]), mapKeys(attributes)))::Tuple(name String, timestamp String, fields Array(Map(String, String))), `Events.Name`, `Events.Timestamp`, `Events.Attributes`) AS logs,\n\tarrayMap((traceID, spanID, attributes) -> tuple(traceID, spanID, arrayMap(key -> map('key', key, 'value', attributes[key]), mapKeys(attributes)))::Tuple(traceID String, spanID String, tags Array(Map(String, String))), `Links.TraceId`, `Links.SpanId`, `Links.Attributes`) AS references\nFROM otel.otel_traces\nWHERE\n\ttraceID = trace_id AND startTime >= trace_start AND startTime <= trace_end AND ( Duration > 0 )\nORDER BY Timestamp DESC, Duration DESC\nLIMIT 1000", - "refId": "A" - } - ], - "title": "Trace Details", - "type": "traces" - }, - { - "datasource": { - "type": "grafana-clickhouse-datasource", - "uid": "clickhouse" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "bars", - "fillOpacity": 24, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 40 - }, - "id": 8, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "multi", - "sort": "desc" - } - }, - "pluginVersion": "11.5.2", - "targets": [ - { - "datasource": { - "type": "grafana-clickhouse-datasource", - "uid": "clickhouse-traces" - }, - "editorType": "sql", - "format": 0, - "meta": { - "builderOptions": { - "aggregates": [ - { - "aggregateType": "count", - "column": "" - } - ], - "columns": [ - { - "hint": "time", - "name": "Timestamp", - "type": "DateTime64(9)" - } - ], - "database": "otel", - "filters": [ - { - "condition": "AND", - "filterType": "custom", - "hint": "time", - "key": "Timestamp", - "operator": "WITH IN DASHBOARD TIME RANGE", - "restrictToFields": [ - { - "label": "Timestamp", - "name": "Timestamp", - "picklistValues": [], - "type": "DateTime64(9)" - } - ], - "type": "datetime" - } - ], - "groupBy": [ - "ServiceName" - ], - "limit": 10000, - "mode": "trend", - "orderBy": [], - "queryType": "timeseries", - "table": "otel_traces" - } - }, - "pluginVersion": "4.0.6", - "queryType": "timeseries", - "rawSql": "SELECT\r\n $__timeInterval(Timestamp) as time,\r\n count(*) as ` `,\r\n ServiceName\r\nFROM otel.otel_traces\r\nWHERE\r\n $__conditionalAll(TraceId IN (${trace_id:singlequote}), $trace_id)\r\n AND ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )\r\n AND ServiceName IN (${service_name:singlequote})\r\n AND SpanName IN (${span_name:singlequote})\r\n AND (($ray_id, NULL).1 = 'All' ? true : SpanAttributes['ray_id'] IN (${ray_id:singlequote}))\r\n AND (($workflow_id, NULL).1 = 'All' ? true : SpanAttributes['workflow_id'] IN (${workflow_id:singlequote}))\r\n AND StatusCode IN ('Error', 'STATUS_CODE_ERROR')\r\n AND ServiceName != 'loadgenerator' GROUP BY ServiceName, time\r\nORDER BY time ASC\r\nLIMIT 100000", - "refId": "A" - } - ], - "title": "Error rates", - "type": "timeseries" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 49 - }, - "id": 10, - "panels": [ - { - "datasource": { - "type": "grafana-clickhouse-datasource", - "uid": "clickhouse" - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 24, - "x": 0, - "y": 61 - }, - "id": 11, - "options": { - "dedupStrategy": "none", - "enableInfiniteScrolling": false, - "enableLogDetails": true, - "prettifyLogMessage": false, - "showCommonLabels": false, - "showLabels": false, - "showTime": true, - "sortOrder": "Descending", - "wrapLogMessage": false - }, - "pluginVersion": "11.5.2", - "targets": [ - { - "builderOptions": { - "columns": [ - { - "hint": "time", - "name": "Timestamp", - "type": "DateTime64(9)" - }, - { - "hint": "log_level", - "name": "SeverityText", - "type": "LowCardinality(String)" - }, - { - "hint": "log_message", - "name": "Body", - "type": "String" - } - ], - "database": "otel", - "filters": [], - "limit": 1000, - "meta": { - "logMessageLike": "", - "otelVersion": "latest" - }, - "mode": "list", - "orderBy": [], - "queryType": "logs", - "table": "otel_logs" - }, - "datasource": { - "type": "grafana-clickhouse-datasource", - "uid": "clickhouse" - }, - "editorType": "builder", - "format": 2, - "pluginVersion": "4.0.6", - "rawSql": "SELECT Timestamp as timestamp, Body as body, SeverityText as level FROM \"otel\".\"otel_logs\" LIMIT 1000", - "refId": "A" - } - ], - "title": "Trace Logs", - "type": "logs" - } - ], - "title": "Logs", - "type": "row" - } - ], - "preload": false, - "refresh": "", - "schemaVersion": 40, - "tags": [], - "templating": { - "list": [ - { - "current": { - "text": "ClickHouse", - "value": "ClickHouse" - }, - "includeAll": false, - "label": "ClickHouse instance", - "name": "datasource", - "options": [], - "query": "grafana-clickhouse-datasource", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "current": { - "text": [ - "All" - ], - "value": [ - "$__all" - ] - }, - "datasource": { - "type": "grafana-clickhouse-datasource", - "uid": "clickhouse" - }, - "definition": "SELECT DISTINCT ServiceName FROM otel.otel_traces", - "includeAll": true, - "label": "Service Name", - "multi": true, - "name": "service_name", - "options": [], - "query": "SELECT DISTINCT ServiceName FROM otel.otel_traces", - "refresh": 1, - "regex": "", - "type": "query" - }, - { - "current": { - "text": "All", - "value": "$__all" - }, - "datasource": { - "type": "grafana-clickhouse-datasource", - "uid": "clickhouse" - }, - "definition": "SELECT DISTINCT TraceId FROM otel.otel_traces WHERE ParentSpanId = '' LIMIT 100", - "includeAll": true, - "label": "Trace ID", - "name": "trace_id", - "options": [], - "query": "SELECT DISTINCT TraceId FROM otel.otel_traces WHERE ParentSpanId = '' LIMIT 100", - "refresh": 1, - "regex": "", - "type": "query" - }, - { - "current": { - "text": [ - "All" - ], - "value": [ - "$__all" - ] - }, - "datasource": { - "type": "grafana-clickhouse-datasource", - "uid": "clickhouse" - }, - "definition": "SELECT DISTINCT SpanName FROM otel.otel_traces WHERE ServiceName IN (${service_name:singlequote}) LIMIT 1000;", - "description": "", - "includeAll": true, - "label": "Span", - "multi": true, - "name": "span_name", - "options": [], - "query": "SELECT DISTINCT SpanName FROM otel.otel_traces WHERE ServiceName IN (${service_name:singlequote}) LIMIT 1000;", - "refresh": 1, - "regex": "", - "type": "query" - }, - { - "allValue": "'All'", - "current": { - "text": [ - "All" - ], - "value": [ - "$__all" - ] - }, - "datasource": { - "type": "grafana-clickhouse-datasource", - "uid": "clickhouse" - }, - "definition": "SELECT DISTINCT SpanAttributes['ray_id'] FROM otel.otel_traces WHERE SpanAttributes['ray_id'] != '' AND ServiceName IN (${service_name:singlequote}) LIMIT 1000;", - "description": "", - "includeAll": true, - "label": "Ray ID", - "multi": true, - "name": "ray_id", - "options": [], - "query": "SELECT DISTINCT SpanAttributes['ray_id'] FROM otel.otel_traces WHERE SpanAttributes['ray_id'] != '' AND ServiceName IN (${service_name:singlequote}) LIMIT 1000;", - "refresh": 1, - "regex": "", - "type": "query" - }, - { - "allValue": "'All'", - "current": { - "text": [ - "All" - ], - "value": [ - "$__all" - ] - }, - "datasource": { - "type": "grafana-clickhouse-datasource", - "uid": "clickhouse" - }, - "definition": "SELECT DISTINCT SpanAttributes['workflow_id'] FROM otel.otel_traces WHERE SpanAttributes['workflow_id'] != '' AND ServiceName IN (${service_name:singlequote}) LIMIT 1000;", - "description": "", - "includeAll": true, - "label": "Workflow ID", - "multi": true, - "name": "workflow_id", - "options": [], - "query": "SELECT DISTINCT SpanAttributes['workflow_id'] FROM otel.otel_traces WHERE SpanAttributes['workflow_id'] != '' AND ServiceName IN (${service_name:singlequote}) LIMIT 1000;", - "refresh": 1, - "regex": "", - "type": "query" - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": {}, - "timezone": "America/Los_Angeles", - "title": "Traces", - "uid": "8klBUGfVk", - "version": 2, - "weekStart": "" -} \ No newline at end of file diff --git a/docker/dev-full/grafana/grafana.ini b/docker/dev-full/grafana/grafana.ini deleted file mode 100644 index c8e434623d..0000000000 --- a/docker/dev-full/grafana/grafana.ini +++ /dev/null @@ -1,6 +0,0 @@ -[auth] -disable_login_form = true - -[auth.anonymous] -enabled = true -org_role = Admin diff --git a/docker/dev-full/grafana/provisioning/dashboards/dashboards.yaml b/docker/dev-full/grafana/provisioning/dashboards/dashboards.yaml deleted file mode 100644 index 1a8b4c5e61..0000000000 --- a/docker/dev-full/grafana/provisioning/dashboards/dashboards.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: 1 - -providers: - - name: 'default' - type: file - options: - path: '/var/lib/grafana/dashboards' diff --git a/docker/dev-full/grafana/provisioning/datasources/datasources.yaml b/docker/dev-full/grafana/provisioning/datasources/datasources.yaml deleted file mode 100644 index 0d3f640ce0..0000000000 --- a/docker/dev-full/grafana/provisioning/datasources/datasources.yaml +++ /dev/null @@ -1,53 +0,0 @@ -apiVersion: 1 - -datasources: - - name: Prometheus - uid: prometheus - type: prometheus - access: proxy - url: http://prometheus:9090 - isDefault: true - jsonData: - httpMethod: POST - timeInterval: "5s" - - - name: ClickHouse - uid: clickhouse - type: grafana-clickhouse-datasource - secureJsonData: - password: default - jsonData: - version: "2.0.0" - host: clickhouse - port: 8123 - defaultDatabase: default - protocol: http - secure: false - username: default - validateSql: true - logs: - otelEnabled: true - otelVersion: "1.2.9" - defaultDatabase: otel - defaultTable: otel_logs - timeColumn: TimestampTime - messageColumn: Body - levelColumn: SeverityText - traces: - otelEnabled: true - otelVersion: "1.2.9" - defaultDatabase: otel - defaultTable: otel_traces - - # These cause bugs if defined, leave the default values - # (Specifically duration, it by default uses a `multiply(...)`, but it doesn't if specified here) - # traceIdColumn: TraceId - # spanIdColumn: SpanId - # operationNameColumn: SpanName - # parentSpanIdColumn: ParentSpanId - # serviceNameColumn: ServiceName - # durationColumn: Duration - # durationUnit: nanoseconds - # startTimeColumn: Timestamp - # tagsColumn: SpanAttributes - # serviceTagsColumn: ResourceAttributes diff --git a/docker/dev-full/otel-collector/config.yaml b/docker/dev-full/otel-collector/config.yaml deleted file mode 100644 index 3fb19d663e..0000000000 --- a/docker/dev-full/otel-collector/config.yaml +++ /dev/null @@ -1,68 +0,0 @@ -receivers: - otlp: - protocols: - grpc: - endpoint: 0.0.0.0:4317 - http: - endpoint: 0.0.0.0:4318 - prometheus: - config: - scrape_configs: - - job_name: 'cadvisor' - static_configs: - - targets: ['rivet-client:7780'] - metrics_path: /metrics - scrape_interval: 30s - -processors: - batch: - timeout: 5s - send_batch_size: 10000 - -exporters: - clickhouse: - endpoint: http://clickhouse:8123 - database: otel - username: default - password: ${env:CLICKHOUSE_PASSWORD} - async_insert: true - ttl: 72h - compress: lz4 - create_schema: true - logs_table_name: otel_logs - traces_table_name: otel_traces - timeout: 5s - metrics_tables: - gauge: - name: otel_metrics_gauge - sum: - name: otel_metrics_sum - summary: - name: otel_metrics_summary - histogram: - name: otel_metrics_histogram - exponential_histogram: - name: otel_metrics_exp_histogram - retry_on_failure: - enabled: true - initial_interval: 5s - max_interval: 30s - max_elapsed_time: 300s - # debug: - # verbosity: detailed - -service: - pipelines: - logs: - receivers: [otlp] - processors: [batch] - exporters: [clickhouse] - traces: - receivers: [otlp] - processors: [batch] - exporters: [clickhouse] - metrics: - receivers: [otlp, prometheus] - processors: [batch] - exporters: [clickhouse] - diff --git a/docker/dev-full/prometheus/prometheus.yml b/docker/dev-full/prometheus/prometheus.yml deleted file mode 100644 index b080fff210..0000000000 --- a/docker/dev-full/prometheus/prometheus.yml +++ /dev/null @@ -1,17 +0,0 @@ -global: - scrape_interval: 5s - evaluation_interval: 5s - -scrape_configs: - - job_name: rivet-server - static_configs: - - targets: - - rivet-server:8091 - - job_name: rivet-edge-server - static_configs: - - targets: - - rivet-edge-server:8091 - - job_name: rivet-client - static_configs: - - targets: - - rivet-client:6090 diff --git a/docker/dev-full/rivet-client/config.jsonc b/docker/dev-full/rivet-client/config.jsonc deleted file mode 100644 index d70236be07..0000000000 --- a/docker/dev-full/rivet-client/config.jsonc +++ /dev/null @@ -1,63 +0,0 @@ -{ - "client": { - "runner": { - "flavor": "container", - // Resource constraints are not supported in Docker - // TODO: Needs further investigation in to why nested cgroups v2 resource constraints aren't working - "use_resource_constraints": false, - "custom_hosts": [ - // Define host for the API server - // - // This is a custom IP defined in entrypoint.sh iptables - { - "ip": "192.168.100.1", - "hostname": "rivet-server" - } - ] - }, - "cluster": { - // This is safe to hardcode - "client_id": "fc67e54e-5d6a-4726-ab23-77b0e54f068f", - "api_endpoint": "http://rivet-server:6420", - "ws_addresses": { - "static": [ - "rivet-edge-server:6422" - ] - } - }, - // TODO: Compare this to network in cluster config - "network": { - "bind_ip": "127.0.0.1", - // Point to DNS name inside Docker container - "lan_hostname": "rivet-client", - // Point to localhost since this is a dev instance - "wan_hostname": "127.0.0.1", - // Corresponds to the port range configured in the `docker-compose.yml` - "wan_port_range_min": 7600, - "wan_port_range_max": 7699 - }, - "cni": { - "network_interface": "eth0" - }, - // Don't reserve any resources on dev instances - "reserved_resources": { - "cpu": 0, - "memory": 0 - }, - "logs": { - "redirect_logs": true - }, - "foundationdb": { - "cluster_description": "docker", - "cluster_id": "docker", - "addresses": { - "static": [ - "foundationdb:4500" - ] - } - }, - "vector": { - "address": "vector-server:6100" - } - } -} diff --git a/docker/dev-full/rivet-client/entrypoint.sh b/docker/dev-full/rivet-client/entrypoint.sh deleted file mode 100755 index 4a33223670..0000000000 --- a/docker/dev-full/rivet-client/entrypoint.sh +++ /dev/null @@ -1,294 +0,0 @@ -#!/bin/bash -set -euf - -# SEE ALSO: packages/core/services/cluster/src/workflows/server/install/install_scripts/files/pegboard_configure.sh - -# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# -# DO NOT CHANGE NETWORKING CONFIGS WITHOUT MANUALLY RE-TESTING RULES -# -# There are no automated tests to validate that iptables -# and tc correctly marks traffic priorities. Manually -# check the following if you change this file. -# -# 1. Restart the game node(s) to make sure there are -# fresh iptables & tc rules. -# 2. Run `tc -s class show dev eth1` and start a lobby. -# Make sure packets are passing through 1:10 (Game -# Guard traffic) and 1:20 (ATS traffic). -# 3. Run `iptables -L -v` and validate that packets are -# flowing through *ALL* rules in the RIVET-ADMIN chain -# (for game traffic) and the RIVET-INPUT chain (for ATS -# traffic). -# 4. Run `iptables -L -v -t mangle` and validate that -# packets are flowing through *ALL* the rules in -# RIVET-ADMIN and RIVET-INPUT. -# 5. Obviously, make sure both bridge and host networking -# works. The lobby connectivity tests cover this. -# -# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -ADMIN_CHAIN="RIVET-ADMIN" -NAT_CHAIN="RIVET-NAT" -SUBNET_IPV4="172.26.64.0/20" -SUBNET_IPV6="fd00:db8:2::/64" -RIVET_SERVER_IPV4="192.168.100.1" - -# Create admin chain that only accepts traffic from the GG subnet -# PUBLIC_IFACE="eth0" -# VLAN_IFACE="eth1" -# GG_VLAN_SUBNET="0.0.0.0/0" - -# # MARK: Linux Traffic Control -# for iface in $PUBLIC_IFACE $VLAN_IFACE; do -# # Check if the HTB qdisc already exists -# if ! tc qdisc show dev $iface | grep -q "htb 1:"; then -# -# # Set up a HTB queuing discipline. -# # -# # This will help prioritize traffic in the case of congestion. -# # -# # HTB was chosen over QCB because it allows for more flexibility in the future. -# # -# # Manually test that traffic is getting routed correctly by running: -# # tc -s class show dev eth1 -# # -# # Read more: https://lartc.org/howto/lartc.qdisc.classful.html#AEN1071 -# tc qdisc add dev $iface \ -# root \ -# handle 1: \ -# htb \ -# default 10 -# -# # Create a root class with a max bandwidth -# tc class add dev $iface \ -# parent 1: \ -# classid 1:1 \ -# htb \ -# rate 10Gbit -# -# # Game traffic class with high priority -# # -# # Low bandwidth limit = game servers are not expected to use much bandwidth -# # High priority = packets take priority in the case of congestion -# tc class add dev $iface \ -# parent 1:1 \ -# classid 1:10 \ -# htb \ -# rate 100Mbit \ -# prio 0 -# -# # Background traffic class with lower priority -# # -# # High bandwidth = peak performance when there is no network congestion -# # Low priority = packets are dropped first in the case of congestion -# tc class add dev $iface \ -# parent 1:1 \ -# classid 1:20 \ -# htb \ -# rate 1000Mbit \ -# prio 1 -# -# # Forward packets with different marks to the appropriate classes. -# # -# # prio x = sets filter priority -# # handle x = handle packets marked x by iptables -# # fw classid x = send matched packets to class x -# # action change dsfield set x = set the packet's TOS (0x10 = low delay, 0x8 = high throughput) -# tc filter add dev $iface \ -# protocol ip \ -# parent 1:0 \ -# prio 1 \ -# handle 1 \ -# fw classid 1:10 -# tc filter add dev $iface \ -# protocol ip \ -# parent 1:0 \ -# prio 2 \ -# handle 2 \ -# fw classid 1:20 -# -# echo "HTB qdisc and class rules added." -# -# else -# echo "HTB qdisc and class rules already exist." -# fi -# done - -# MARK: iptables -add_ipt_chain() { - local ipt="$1" - local table="$2" - local chain="$3" - - if ! "$ipt" -t "$table" -L "$chain" &>/dev/null; then - "$ipt" -t "$table" -N "$chain" - echo "Created $ipt $table chain: $chain" - else - echo "Chain already exists in $ipt $table: $chain" - fi -} - -add_ipt_rule() { - local ipt="$1" - local table="$2" - local chain="$3" - local rule="$4" - - if ! "$ipt" -t $table -C "$chain" $rule &>/dev/null; then - "$ipt" -t $table -A "$chain" $rule - echo "Added $ipt $table $chain rule: $rule" - else - echo "Rule already exists in $ipt $table $chain: $rule" - fi -} - -for ipt in iptables ip6tables; do - # Define SUBNET_VAR based on iptables version - if [ "$ipt" == "iptables" ]; then - SUBNET_VAR="$SUBNET_IPV4" - else - SUBNET_VAR="$SUBNET_IPV6" - fi - - # MARK: Chains - add_ipt_chain "$ipt" "filter" "$ADMIN_CHAIN" - add_ipt_chain "$ipt" "nat" "$NAT_CHAIN" - - # Jump to RIVET-NAT chain from OUTPUT (for locally generated traffic) - # and PREROUTING (for container traffic) - # - # CNI firewall plugin will automatically jump to $ADMIN_CHAIN on "filter" - add_ipt_rule "$ipt" "nat" "OUTPUT" "-j $NAT_CHAIN" - add_ipt_rule "$ipt" "nat" "PREROUTING" "-j $NAT_CHAIN" - - # TODO: This IP will change - # MARK: Expose rivet-server inside the container at 192.168.100.1 - # Only applicable to IPv4 (assuming Docker networking stack is IPv4 only) - if [ "$ipt" == "iptables" ]; then - RIVET_SERVER_HOST="$(dig +short rivet-server)" - echo "Adding rule to forward $RIVET_SERVER_IPV4 to rivet-server ($RIVET_SERVER_HOST)" - add_ipt_rule "$ipt" "nat" "$NAT_CHAIN" "-d $RIVET_SERVER_IPV4 -j DNAT --to-destination $RIVET_SERVER_HOST" - - fi - - # add_ipt_chain "$ipt" "mangle" "RIVET-FORWARD" - # add_ipt_rule "$ipt" "mangle" "FORWARD" "-j RIVET-FORWARD" - # - # add_ipt_chain "$ipt" "filter" "RIVET-INPUT" - # add_ipt_rule "$ipt" "filter" "INPUT" "-j RIVET-INPUT" - # - # add_ipt_chain "$ipt" "mangle" "RIVET-INPUT" - # add_ipt_rule "$ipt" "mangle" "INPUT" "-j RIVET-INPUT" - # - # # MARK: Create GG TOS - # # - # # Sets the TOS to minimize delay if not already set. - # if ! "$ipt" -t mangle -L "RIVET-TOS-GG" &>/dev/null; then - # "$ipt" -t mangle -N "RIVET-TOS-GG" - # echo "Created $ipt chain: RIVET-TOS-GG" - # else - # echo "Chain already exists in $ipt: RIVET-TOS-GG" - # fi - # add_ipt_rule "$ipt" "mangle" "RIVET-TOS-GG" "-m tos ! --tos 0x0 -j RETURN" - # add_ipt_rule "$ipt" "mangle" "RIVET-TOS-GG" "-j TOS --set-tos 0x10" - # - # # VLAN only applicable to IPv4 - # if [ "$ipt" == "iptables" ]; then - # # MARK: GG TOS - # add_ipt_rule "$ipt" "mangle" "RIVET-FORWARD" "-s $GG_VLAN_SUBNET -d $SUBNET_VAR -j RIVET-TOS-GG" - # add_ipt_rule "$ipt" "mangle" "RIVET-FORWARD" "-s $SUBNET_VAR -d $GG_VLAN_SUBNET -j RIVET-TOS-GG" - # - # # MARK: GG ingress - # # Prioritize traffic - # add_ipt_rule "$ipt" "filter" "$ADMIN_CHAIN" "-s $GG_VLAN_SUBNET -d $SUBNET_VAR -j MARK --set-mark 1" - # # Accept traffic - # add_ipt_rule "$ipt" "filter" "$ADMIN_CHAIN" "-s $GG_VLAN_SUBNET -d $SUBNET_VAR -j ACCEPT" - # - # # MARK: GG egress - # # Prioritize response traffic - # add_ipt_rule "$ipt" "filter" "$ADMIN_CHAIN" "-s $SUBNET_VAR -m conntrack --ctstate NEW,ESTABLISHED -j MARK --set-mark 1" - # # Enable conntrack to allow traffic to flow back to the GG subnet - # add_ipt_rule "$ipt" "filter" "$ADMIN_CHAIN" "-s $SUBNET_VAR -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT" - # - # # MARK: ATS ingress - # # Maximize throughput from ATS - # add_ipt_rule "$ipt" "mangle" "RIVET-INPUT" "-s __ATS_VLAN_SUBNET__ -j TOS --set-tos Maximize-Throughput" - # # Deprioritize traffic so game traffic takes priority - # add_ipt_rule "$ipt" "filter" "RIVET-INPUT" "-s __ATS_VLAN_SUBNET__ -j MARK --set-mark 2" - # fi - # - # # MARK: Public egress - # # Prioritize traffic - # add_ipt_rule "$ipt" "filter" "$ADMIN_CHAIN" "-s $SUBNET_VAR -o $PUBLIC_IFACE -j MARK --set-mark 1" - # # Allow egress traffic - # add_ipt_rule "$ipt" "filter" "$ADMIN_CHAIN" "-s $SUBNET_VAR -o $PUBLIC_IFACE -j ACCEPT" - # - # # Allow public ingress traffic on all ports because this is already mapped by CNI - # add_ipt_rule "$ipt" "filter" "$ADMIN_CHAIN" "-p tcp -d $SUBNET_VAR -i $PUBLIC_IFACE -j ACCEPT" - # add_ipt_rule "$ipt" "filter" "$ADMIN_CHAIN" "-p udp -d $SUBNET_VAR -i $PUBLIC_IFACE -j ACCEPT" - # - # # MARK: Deny - # # Deny all other egress traffic - # add_ipt_rule "$ipt" "filter" "$ADMIN_CHAIN" "-s $SUBNET_VAR -j DROP" -done - -# MARK: CNI -# -# Dual-stack CNI config -# -# We use ptp instead of bridge networking in order to isolate the pod's traffic. It's also more performant than bridge networking. -cat << EOF > /opt/cni/config/rivet-actor.conflist -{ - "cniVersion": "0.4.0", - "name": "rivet-actor", - "plugins": [ - { - "type": "loopback" - }, - { - "type": "ptp", - "ipMasq": true, - "ipam": { - "type": "host-local", - "ranges": [ - [ - { "subnet": "$SUBNET_IPV4" } - ], - [ - { "subnet": "$SUBNET_IPV6" } - ] - ], - "routes": [ - { "dst": "0.0.0.0/0" }, - { "dst": "::/0" } - ] - }, - "dns": { - "nameservers": [ - "8.8.8.8", - "8.8.4.4", - "2001:4860:4860::8888", - "2001:4860:4860::8844" - ], - "options": ["rotate", "edns0", "attempts:2"] - } - }, - { - "type": "firewall", - "backend": "iptables", - "iptablesAdminChainName": "$ADMIN_CHAIN" - }, - { - "type": "portmap", - "capabilities": { "portMappings": true }, - "snat": true - } - ] -} -EOF - -# MARK: Entrypoint -echo "Starting client" -rivet-client "$@" - diff --git a/docker/dev-full/rivet-client/rivet-actor.conflist b/docker/dev-full/rivet-client/rivet-actor.conflist deleted file mode 100644 index 7d48a3282f..0000000000 --- a/docker/dev-full/rivet-client/rivet-actor.conflist +++ /dev/null @@ -1,42 +0,0 @@ -{ - "cniVersion": "0.4.0", - "name": "rivet-actor", - "plugins": [ - { - "type": "loopback" - }, - { - "type": "ptp", - "ipMasq": true, - "ipam": { - "type": "host-local", - "ranges": [ - [ - { "subnet": "172.26.64.0/20" } - ], - [ - { "subnet": "fd00:db8:2::/64" } - ] - ], - "routes": [ - { "dst": "0.0.0.0/0" }, - { "dst": "::/0" } - ] - }, - "dns": { - "nameservers": [ - "8.8.8.8", - "8.8.4.4", - "2001:4860:4860::8888", - "2001:4860:4860::8844" - ], - "options": ["rotate", "edns0", "attempts:2"] - } - }, - { - "type": "portmap", - "capabilities": { "portMappings": true }, - "snat": true - } - ] -} diff --git a/docker/dev-full/rivet-client/rivet-setup-networking.sh b/docker/dev-full/rivet-client/rivet-setup-networking.sh deleted file mode 100644 index c3d7df5d6c..0000000000 --- a/docker/dev-full/rivet-client/rivet-setup-networking.sh +++ /dev/null @@ -1,270 +0,0 @@ -#!/bin/sh -set -euf - -# SEE ALSO: packages/core/services/cluster/src/workflows/server/install/install_scripts/files/pegboard_configure.sh - -# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# -# DO NOT CHANGE NETWORKING CONFIGS WITHOUT MANUALLY RE-TESTING RULES -# -# There are no automated tests to validate that iptables -# and tc correctly marks traffic priorities. Manually -# check the following if you change this file. -# -# 1. Restart the game node(s) to make sure there are -# fresh iptables & tc rules. -# 2. Run `tc -s class show dev eth1` and start a lobby. -# Make sure packets are passing through 1:10 (Game -# Guard traffic) and 1:20 (ATS traffic). -# 3. Run `iptables -L -v` and validate that packets are -# flowing through *ALL* rules in the RIVET-ADMIN chain -# (for game traffic) and the RIVET-INPUT chain (for ATS -# traffic). -# 4. Run `iptables -L -v -t mangle` and validate that -# packets are flowing through *ALL* the rules in -# RIVET-ADMIN and RIVET-INPUT. -# 5. Obviously, make sure both bridge and host networking -# works. The lobby connectivity tests cover this. -# -# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -# Create admin chain that only accepts traffic from the GG subnet -# -# See Nomad equivalent: https://github.com/hashicorp/nomad/blob/a8f0f2612ef9d283ed903721f8453a0c0c3f51c5/client/allocrunner/networking_bridge_linux.go#L73 -ADMIN_CHAIN="RIVET-ADMIN" -SUBNET_IPV4="172.26.64.0/20" -SUBNET_IPV6="fd00:db8:2::/64" - -# MARK: Linux Traffic Control -for iface in __PUBLIC_IFACE__ __VLAN_IFACE__; do - # Check if the HTB qdisc already exists - if ! tc qdisc show dev \$iface | grep -q "htb 1:"; then - - # Set up a HTB queuing discipline. - # - # This will help prioritize traffic in the case of congestion. - # - # HTB was chosen over QCB because it allows for more flexibility in the future. - # - # Manually test that traffic is getting routed correctly by running: - # tc -s class show dev eth1 - # - # Read more: https://lartc.org/howto/lartc.qdisc.classful.html#AEN1071 - tc qdisc add dev \$iface \ - root \ - handle 1: \ - htb \ - default 10 - - # Create a root class with a max bandwidth - tc class add dev \$iface \ - parent 1: \ - classid 1:1 \ - htb \ - rate 10Gbit - - # Game traffic class with high priority - # - # Low bandwidth limit = game servers are not expected to use much bandwidth - # High priority = packets take priority in the case of congestion - tc class add dev \$iface \ - parent 1:1 \ - classid 1:10 \ - htb \ - rate 100Mbit \ - prio 0 - - # Background traffic class with lower priority - # - # High bandwidth = peak performance when there is no network congestion - # Low priority = packets are dropped first in the case of congestion - tc class add dev \$iface \ - parent 1:1 \ - classid 1:20 \ - htb \ - rate 1000Mbit \ - prio 1 - - # Forward packets with different marks to the appropriate classes. - # - # prio x = sets filter priority - # handle x = handle packets marked x by iptables - # fw classid x = send matched packets to class x - # action change dsfield set x = set the packet's TOS (0x10 = low delay, 0x8 = high throughput) - tc filter add dev \$iface \ - protocol ip \ - parent 1:0 \ - prio 1 \ - handle 1 \ - fw classid 1:10 - tc filter add dev \$iface \ - protocol ip \ - parent 1:0 \ - prio 2 \ - handle 2 \ - fw classid 1:20 - - echo "HTB qdisc and class rules added." - - else - echo "HTB qdisc and class rules already exist." - fi -done - -# MARK: iptables -add_ipt_chain() { - local ipt="\$1" - local table="\$2" - local chain="\$3" - - if ! "\$ipt" -t "\$table" -L "\$chain" &>/dev/null; then - "\$ipt" -t "\$table" -N "\$chain" - echo "Created \$ipt \$table chain: \$chain" - else - echo "Chain already exists in \$ipt \$table: \$chain" - fi -} - -add_ipt_rule() { - local ipt="\$1" - local table="\$2" - local chain="\$3" - local rule="\$4" - - if ! "\$ipt" -t \$table -C "\$chain" \$rule &>/dev/null; then - "\$ipt" -t \$table -A "\$chain" \$rule - echo "Added \$ipt \$table \$chain rule: \$rule" - else - echo "Rule already exists in \$ipt \$table \$chain: \$rule" - fi -} - -for ipt in iptables ip6tables; do - # Define SUBNET_VAR based on iptables version - if [ "\$ipt" == "iptables" ]; then - SUBNET_VAR="$SUBNET_IPV4" - else - SUBNET_VAR="$SUBNET_IPV6" - fi - - # MARK: Chains - add_ipt_chain "\$ipt" "filter" "$ADMIN_CHAIN" - - add_ipt_chain "\$ipt" "mangle" "RIVET-FORWARD" - add_ipt_rule "\$ipt" "mangle" "FORWARD" "-j RIVET-FORWARD" - - add_ipt_chain "\$ipt" "filter" "RIVET-INPUT" - add_ipt_rule "\$ipt" "filter" "INPUT" "-j RIVET-INPUT" - - add_ipt_chain "\$ipt" "mangle" "RIVET-INPUT" - add_ipt_rule "\$ipt" "mangle" "INPUT" "-j RIVET-INPUT" - - # MARK: Create GG TOS - # - # Sets the TOS to minimize delay if not already set. - if ! "\$ipt" -t mangle -L "RIVET-TOS-GG" &>/dev/null; then - "\$ipt" -t mangle -N "RIVET-TOS-GG" - echo "Created \$ipt chain: RIVET-TOS-GG" - else - echo "Chain already exists in \$ipt: RIVET-TOS-GG" - fi - add_ipt_rule "\$ipt" "mangle" "RIVET-TOS-GG" "-m tos ! --tos 0x0 -j RETURN" - add_ipt_rule "\$ipt" "mangle" "RIVET-TOS-GG" "-j TOS --set-tos 0x10" - - # VLAN only applicable to IPv4 - if [ "\$ipt" == "iptables" ]; then - # MARK: GG TOS - add_ipt_rule "\$ipt" "mangle" "RIVET-FORWARD" "-s __GG_VLAN_SUBNET__ -d \$SUBNET_VAR -j RIVET-TOS-GG" - add_ipt_rule "\$ipt" "mangle" "RIVET-FORWARD" "-s \$SUBNET_VAR -d __GG_VLAN_SUBNET__ -j RIVET-TOS-GG" - - # MARK: GG ingress - # Prioritize traffic - add_ipt_rule "\$ipt" "filter" "$ADMIN_CHAIN" "-s __GG_VLAN_SUBNET__ -d \$SUBNET_VAR -j MARK --set-mark 1" - # Accept traffic - add_ipt_rule "\$ipt" "filter" "$ADMIN_CHAIN" "-s __GG_VLAN_SUBNET__ -d \$SUBNET_VAR -j ACCEPT" - - # MARK: GG egress - # Prioritize response traffic - add_ipt_rule "\$ipt" "filter" "$ADMIN_CHAIN" "-s \$SUBNET_VAR -m conntrack --ctstate NEW,ESTABLISHED -j MARK --set-mark 1" - # Enable conntrack to allow traffic to flow back to the GG subnet - add_ipt_rule "\$ipt" "filter" "$ADMIN_CHAIN" "-s \$SUBNET_VAR -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT" - - # MARK: ATS ingress - # Maximize throughput from ATS - add_ipt_rule "\$ipt" "mangle" "RIVET-INPUT" "-s __ATS_VLAN_SUBNET__ -j TOS --set-tos Maximize-Throughput" - # Deprioritize traffic so game traffic takes priority - add_ipt_rule "\$ipt" "filter" "RIVET-INPUT" "-s __ATS_VLAN_SUBNET__ -j MARK --set-mark 2" - fi - - # MARK: Public egress - # Prioritize traffic - add_ipt_rule "\$ipt" "filter" "$ADMIN_CHAIN" "-s \$SUBNET_VAR -o __PUBLIC_IFACE__ -j MARK --set-mark 1" - # Allow egress traffic - add_ipt_rule "\$ipt" "filter" "$ADMIN_CHAIN" "-s \$SUBNET_VAR -o __PUBLIC_IFACE__ -j ACCEPT" - - # Allow public ingress traffic on all ports because this is already mapped by CNI - add_ipt_rule "\$ipt" "filter" "$ADMIN_CHAIN" "-p tcp -d \$SUBNET_VAR -i __PUBLIC_IFACE__ -j ACCEPT" - add_ipt_rule "\$ipt" "filter" "$ADMIN_CHAIN" "-p udp -d \$SUBNET_VAR -i __PUBLIC_IFACE__ -j ACCEPT" - - # MARK: Deny - # Deny all other egress traffic - add_ipt_rule "\$ipt" "filter" "$ADMIN_CHAIN" "-s \$SUBNET_VAR -j DROP" -done - -# MARK: CNI -# -# Dual-stack CNI config -# -# We use ptp instead of bridge networking in order to isolate the pod's traffic. It's also more performant than bridge networking. -# -# See default Nomad configuration: https://github.com/hashicorp/nomad/blob/a8f0f2612ef9d283ed903721f8453a0c0c3f51c5/client/allocrunner/networking_bridge_linux.go#L152 -cat << EOF > /opt/cni/config/rivet-actor.conflist -{ - "cniVersion": "0.4.0", - "name": "rivet-actor", - "plugins": [ - { - "type": "loopback" - }, - { - "type": "ptp", - "ipMasq": true, - "ipam": { - "type": "host-local", - "ranges": [ - [ - { "subnet": "$SUBNET_IPV4" } - ], - [ - { "subnet": "$SUBNET_IPV6" } - ] - ], - "routes": [ - { "dst": "0.0.0.0/0" }, - { "dst": "::/0" } - ] - }, - "dns": { - "nameservers": [ - "8.8.8.8", - "8.8.4.4", - "2001:4860:4860::8888", - "2001:4860:4860::8844" - ], - "options": ["rotate", "edns0", "attempts:2"] - } - }, - { - "type": "firewall", - "backend": "iptables", - "iptablesAdminChainName": "$ADMIN_CHAIN" - }, - { - "type": "portmap", - "capabilities": { "portMappings": true }, - "snat": true - } - ] -} -EOF - diff --git a/docker/dev-full/rivet-edge-server/config.jsonc b/docker/dev-full/rivet-edge-server/config.jsonc deleted file mode 100644 index 1619be1563..0000000000 --- a/docker/dev-full/rivet-edge-server/config.jsonc +++ /dev/null @@ -1,103 +0,0 @@ -{ - "server": { - "rivet": { - "auth": { - "access_kind": "development" - }, - "edge": { - "cluster_id": "11ca8960-acab-4963-909c-99d72af3e1cb", - "datacenter_id": "f288913c-735d-4188-bf9b-2fcf6eac7b9c", - "server_id": "174aca2a-98b7-462c-9ad9-3835094a9a10", - "intercom_endpoint": "http://rivet-server:6421" - }, - "guard": { - // TLS not configured for local development - "tls_enabled": false, - // Corresponds to the ports configured in the `docker-compose.yml` - "http_port": 7080, - "https_port": 7443, - "min_ingress_port_tcp": 7500, - "max_ingress_port_tcp": 7599, - "min_ingress_port_udp": 7500, - "max_ingress_port_udp": 7599 - }, - // Enable status checks if testing status check project - "status": { - "token": "local", - "system_test_project": "default", - "system_test_environment": "default" - }, - "metrics": { - "host": "0.0.0.0" - } - }, - "foundationdb": { - "cluster_description": "docker", - "cluster_id": "docker", - "addresses": { - "static": [ - "foundationdb:4500" - ] - } - }, - "cockroachdb": { - "url": "postgresql://cockroachdb:26257/defaultdb?sslmode=disable", - "cluster_identifier": "default", - "username": "root" - }, - "redis": { - "ephemeral": { - "url": "redis://redis:6379", - "password": "password" - }, - "persistent": { - "url": "redis://redis:6379", - "password": "password" - } - }, - "clickhouse": { - "http_url": "http://clickhouse:8123", - "native_url": "clickhouse://clickhouse:9000", - "username": "default", - "password": "default", - "provision_users": { - "vector": { - "username": "vector", - "password": "vector", - "role": "write" - } - } - }, - "vector_http": { - "host": "vector-client", - "port": 5022 - }, - "prometheus": { - "url": "http://prometheus:9090" - }, - "s3": { - "region": "us-east-1", - "endpoint_internal": "http://seaweedfs:9000", - "endpoint_edge_internal": "http://seaweedfs:9000", - "endpoint_external": "http://127.0.0.1:9000", - "access_key_id": "admin", - "secret_access_key": "admin" - }, - "nats": { - "addresses": { - "static": [ - "nats:4222" - ] - } - }, - // IMPORTANT: - // - Generate your own JWT tokens before shipping to production as seen in the - // self-hosting documentation. - // - Do not include the private key in this file. Instead, use the env var - // `RIVET__SERVER__JWT__PRIVATE`. - "jwt": { - "public": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAx7S9ab9ErA50y0tVfFro919+BBxFSuwMKmcJ5QI853Y=\n-----END PUBLIC KEY-----\n", - "private": "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIDI+WHFytxvdtfGot36NMCI26s2Yp0+E5u9OiPf3NQX3\n-----END PRIVATE KEY-----\n" - } - } -} diff --git a/docker/dev-full/rivet-guard/config.jsonc b/docker/dev-full/rivet-guard/config.jsonc deleted file mode 100644 index 7e56b42f5d..0000000000 --- a/docker/dev-full/rivet-guard/config.jsonc +++ /dev/null @@ -1,115 +0,0 @@ -{ - "guard": { - "http_port": 7080, - "https": { - "port": 7443, - "tls": { - "actor_cert_path": "/etc/rivet-server/tls/job_cert.pem", - "actor_key_path": "/etc/rivet-server/tls/job_key.pem", - "api_cert_path": "/etc/rivet-server/tls/api_cert.pem", - "api_key_path": "/etc/rivet-server/tls/api_key.pem" - } - } - }, - "server": { - "rivet": { - "auth": { - "access_kind": "development" - }, - "edge": { - "cluster_id": "11ca8960-acab-4963-909c-99d72af3e1cb", - "datacenter_id": "f288913c-735d-4188-bf9b-2fcf6eac7b9c", - "server_id": "174aca2a-98b7-462c-9ad9-3835094a9a10", - "intercom_endpoint": "http://rivet-server:6421" - }, - "guard": { - // TLS not configured for local development - "tls_enabled": false, - // Corresponds to the ports configured in the `docker-compose.yml` - "http_port": 7080, - "https_port": 7443, - "min_ingress_port_tcp": 7500, - "max_ingress_port_tcp": 7599, - "min_ingress_port_udp": 7500, - "max_ingress_port_udp": 7599 - }, - // Enable status checks if testing status check project - "status": { - "token": "local", - "system_test_project": "default", - "system_test_environment": "default" - }, - "metrics": { - "host": "0.0.0.0" - } - }, - "foundationdb": { - "cluster_description": "docker", - "cluster_id": "docker", - "addresses": { - "static": [ - "foundationdb:4500" - ] - } - }, - "cockroachdb": { - "url": "postgresql://cockroachdb:26257/defaultdb?sslmode=disable", - "cluster_identifier": "default", - "username": "root" - }, - "redis": { - "ephemeral": { - "url": "redis://redis:6379", - "password": "password" - }, - "persistent": { - "url": "redis://redis:6379", - "password": "password" - } - }, - "clickhouse": { - "http_url": "http://clickhouse:8123", - "native_url": "clickhouse://clickhouse:9000", - "username": "default", - "password": "default", - "provision_users": { - "vector": { - "username": "vector", - "password": "vector", - "role": "write" - } - } - }, - "vector_http": { - "host": "vector-client", - "port": 5022 - }, - "prometheus": { - "url": "http://prometheus:9090" - }, - "s3": { - "region": "us-east-1", - "endpoint_internal": "http://seaweedfs:9000", - "endpoint_edge_internal": "http://seaweedfs:9000", - "endpoint_external": "http://127.0.0.1:9000", - "access_key_id": "admin", - "secret_access_key": "admin" - }, - "nats": { - "addresses": { - "static": [ - "nats:4222" - ] - } - }, - // IMPORTANT: - // - Generate your own JWT tokens before shipping to production as seen in the - // self-hosting documentation. - // - Do not include the private key in this file. Instead, use the env var - // `RIVET__SERVER__JWT__PRIVATE`. - "jwt": { - "public": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAx7S9ab9ErA50y0tVfFro919+BBxFSuwMKmcJ5QI853Y=\n-----END PUBLIC KEY-----\n", - "private": "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIDI+WHFytxvdtfGot36NMCI26s2Yp0+E5u9OiPf3NQX3\n-----END PRIVATE KEY-----\n" - } - } -} diff --git a/docker/dev-full/rivet-server/config.jsonc b/docker/dev-full/rivet-server/config.jsonc deleted file mode 100644 index da0fd94196..0000000000 --- a/docker/dev-full/rivet-server/config.jsonc +++ /dev/null @@ -1,98 +0,0 @@ -{ - "server": { - "rivet": { - "auth": { - "access_kind": "development" - }, - "ui": { - "enable": true, - "proxy_origin": "http://frontend-hub:5080", - "public_origin_regex": ".*" - }, - "guard": { - // TLS not configured for local development - "tls_enabled": false, - // Corresponds to the ports configured in the `docker-compose.yml` - "http_port": 7080, - "https_port": 7443, - "min_ingress_port_tcp": 7500, - "max_ingress_port_tcp": 7599, - "min_ingress_port_udp": 7500, - "max_ingress_port_udp": 7599 - }, - // Enable status checks if testing status check project - "status": { - "token": "local", - "system_test_project": "default", - "system_test_environment": "default" - }, - "metrics": { - "host": "0.0.0.0" - } - }, - "foundationdb": { - "cluster_description": "docker", - "cluster_id": "docker", - "addresses": { - "static": [ - "foundationdb:4500" - ] - } - }, - "cockroachdb": { - "url": "postgresql://cockroachdb:26257/defaultdb?sslmode=disable", - "cluster_identifier": "default", - "username": "root" - }, - "redis": { - "ephemeral": { - "url": "redis://redis:6379", - "password": "password" - }, - "persistent": { - "url": "redis://redis:6379", - "password": "password" - } - }, - "clickhouse": { - "http_url": "http://clickhouse:8123", - "native_url": "clickhouse://clickhouse:9000", - "username": "default", - "password": "default", - "provision_users": { - "vector": { - "username": "vector", - "password": "vector", - "role": "write" - } - } - }, - "prometheus": { - "url": "http://prometheus:9090" - }, - "s3": { - "region": "us-east-1", - "endpoint_internal": "http://seaweedfs:9000", - "endpoint_edge_internal": "http://seaweedfs:9000", - "endpoint_external": "http://127.0.0.1:9000", - "access_key_id": "admin", - "secret_access_key": "admin" - }, - "nats": { - "addresses": { - "static": [ - "nats:4222" - ] - } - }, - // IMPORTANT: - // - Generate your own JWT tokens before shipping to production as seen in the - // self-hosting documentation. - // - Do not include the private key in this file. Instead, use the env var - // `RIVET__SERVER__JWT__PRIVATE`. - "jwt": { - "public": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAx7S9ab9ErA50y0tVfFro919+BBxFSuwMKmcJ5QI853Y=\n-----END PUBLIC KEY-----\n", - "private": "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIDI+WHFytxvdtfGot36NMCI26s2Yp0+E5u9OiPf3NQX3\n-----END PRIVATE KEY-----\n" - } - } -} diff --git a/docker/dev-full/seaweedfs/s3.json b/docker/dev-full/seaweedfs/s3.json deleted file mode 100644 index 9b80248742..0000000000 --- a/docker/dev-full/seaweedfs/s3.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "identities": [ - { - "name": "admin", - "credentials": [ - { - "accessKey": "admin", - "secretKey": "admin" - } - ], - "actions": [ - "Admin", - "Read", - "ReadAcp", - "List", - "Tagging", - "Write", - "WriteAcp" - ] - } - ] -} diff --git a/docker/dev-full/vector-client/vector.yaml b/docker/dev-full/vector-client/vector.yaml deleted file mode 100644 index 008feaa39f..0000000000 --- a/docker/dev-full/vector-client/vector.yaml +++ /dev/null @@ -1,112 +0,0 @@ -# See production config at -# ee/packages/services/cluster/src/workflows/server/install/install_scripts/components/vector.rs - -api: - enabled: true - -sources: - prometheus_pegboard: - type: prometheus_scrape - endpoints: - - http://rivet-client:6090 - scrape_interval_secs: 15 - - dynamic_events_http: - type: http_server - address: 0.0.0.0:5022 - encoding: ndjson - - pegboard_manager: - type: file - include: - - /var/lib/rivet-client/log - - pegboard_v8_isolate_runner: - type: file - include: - - /var/lib/rivet-client/runner/log - - pegboard_container_runners: - type: file - include: - - /var/lib/rivet-client/actors/*/log - -transforms: - filter_metrics: - type: filter - inputs: - - prometheus_pegboard - condition: '!starts_with!(.name, "go_") && !starts_with!(.name, "promhttp_")' - - metrics_add_meta: - type: remap - inputs: - - filter_metrics - source: | - .tags.server_id = "fc67e54e-5d6a-4726-ab23-77b0e54f068f" - .tags.datacenter_id = "f288913c-735d-4188-bf9b-2fcf6eac7b9c" - .tags.cluster_id = "unknown" - .tags.pool_type = "pegboard_isolate" - .tags.public_ip = "127.0.0.1" - - pegboard_manager_add_meta: - type: remap - inputs: - - pegboard_manager - source: | - .source = "pegboard_manager" - - .client_id = "fc67e54e-5d6a-4726-ab23-77b0e54f068f" - .server_id = "fc67e54e-5d6a-4726-ab23-77b0e54f068f" - .datacenter_id = "f288913c-735d-4188-bf9b-2fcf6eac7b9c" - .tags.cluster_id = "unknown" - .pool_type = "pegboard_isolate" - .public_ip = "127.0.0.1" - - pegboard_v8_isolate_runner_add_meta: - type: remap - inputs: - - pegboard_v8_isolate_runner - source: | - .source = "pegboard_v8_isolate_runner" - - .client_id = "fc67e54e-5d6a-4726-ab23-77b0e54f068f" - .server_id = "fc67e54e-5d6a-4726-ab23-77b0e54f068f" - .datacenter_id = "f288913c-735d-4188-bf9b-2fcf6eac7b9c" - .tags.cluster_id = "unknown" - .pool_type = "pegboard_isolate" - .public_ip = "127.0.0.1" - - pegboard_container_runner_add_meta: - type: remap - inputs: - - pegboard_container_runners - source: | - .source = "pegboard_container_runner" - .actor_id = parse_regex!(.file, r'/etc/pegboard/actors/(?P[0-9a-fA-F-]+)/log').actor_id - - .client_id = "fc67e54e-5d6a-4726-ab23-77b0e54f068f" - .server_id = "fc67e54e-5d6a-4726-ab23-77b0e54f068f" - .datacenter_id = "f288913c-735d-4188-bf9b-2fcf6eac7b9c" - .cluster_id = "unknown" - .pool_type = "pegboard_isolate" - .public_ip = "127.0.0.1" - -sinks: - vector_sink: - type: vector - inputs: - - metrics_add_meta - - dynamic_events_http - - pegboard_manager_add_meta - - pegboard_v8_isolate_runner_add_meta - - pegboard_container_runner_add_meta - address: vector-server:6000 - healthcheck: - enabled: false - compression: true - buffer: - type: disk - max_size: 268435488 - when_full: block - diff --git a/docker/dev-full/vector-server/vector.yaml b/docker/dev-full/vector-server/vector.yaml deleted file mode 100644 index 9fa0090fcd..0000000000 --- a/docker/dev-full/vector-server/vector.yaml +++ /dev/null @@ -1,173 +0,0 @@ -# See production config at ee/infra/tf/vector/vector.tf - -data_dir: /var/lib/vector - -api: - enabled: true - address: 0.0.0.0:8686 - playground: false - -sources: - vector: - type: vector - address: 0.0.0.0:6000 - - tcp_json: - type: socket - mode: tcp - address: 0.0.0.0:6100 - decoding: - codec: json - - vector_metrics: - type: internal_metrics - - vector_logs: - type: internal_logs - -transforms: - actors: - type: filter - inputs: - - vector - - tcp_json - condition: - type: vrl - source: .source == "actors" - - job_run: - type: filter - inputs: - - vector - - tcp_json - condition: - type: vrl - source: .source == "job_run" - - pegboard: - type: filter - inputs: - - vector - condition: - type: vrl - source: .source == "pegboard_manager" || .source == "pegboard_v8_isolate_runner" - - pegboard_container_runner: - type: filter - inputs: - - vector - condition: - type: vrl - source: .source == "pegboard_container_runner" - - actors_transform: - type: remap - inputs: - - actors - source: | - # Add namespace label to actor logs - .namespace = "rivet" - - clickhouse_dynamic_events_filter: - type: filter - inputs: - - vector - condition: - type: vrl - source: .source == "clickhouse" - - clickhouse_dynamic_events_transform: - type: remap - inputs: - - clickhouse_dynamic_events_filter - source: | - # Extract and store metadata - __database = .database - __table = .table - __columns = .columns - - # Create a new object with just the columns data - . = { - "__database": __database, - "__table": __table, - # By default insert namespace column since most tables include this - "namespace": "rivet" - } - - # Merge in the column data that should be inserted - . = merge!(., __columns) - -sinks: - prom_exporter: - type: prometheus_exporter - inputs: - - vector - - vector_metrics - address: 0.0.0.0:9598 - - console: - type: console - inputs: - - vector_logs - encoding: - codec: text - - clickhouse_actor_logs: - type: clickhouse - inputs: - - actors_transform - compression: gzip - database: db_pegboard_actor_log - endpoint: http://clickhouse:8123 - table: actor_logs3 - auth: - strategy: basic - user: vector - password: vector - batch: - timeout_secs: 1.0 - - clickhouse_job_run_logs: - type: clickhouse - inputs: - - job_run - compression: gzip - database: db_job_log - endpoint: http://clickhouse:8123 - table: run_logs - auth: - strategy: basic - user: vector - password: vector - batch: - timeout_secs: 1.0 - - pegboard_logs: - type: "file" - inputs: ["pegboard"] - path: "/var/log/vector/pegboard/%Y-%m-%d.log" - encoding: - codec: "text" - - pegboard_container_runner_logs: - type: "file" - inputs: ["pegboard_container_runner"] - path: "/var/log/vector/pegboard_container_runner/%Y-%m-%d.log" - encoding: - codec: "text" - - clickhouse_dynamic_events: - type: clickhouse - inputs: - - clickhouse_dynamic_events_transform - compression: gzip - endpoint: http://clickhouse:8123 - database: "{{ __database }}" - table: "{{ __table }}" - auth: - strategy: basic - user: vector - password: vector - batch: - timeout_secs: 1.0 - diff --git a/docker/dev-host/.gitattributes b/docker/dev-host/.gitattributes new file mode 100644 index 0000000000..447edeb5c2 --- /dev/null +++ b/docker/dev-host/.gitattributes @@ -0,0 +1 @@ +. linguist-generated=true diff --git a/docker/dev-host/README.md b/docker/dev-host/README.md new file mode 100644 index 0000000000..1ace063f21 --- /dev/null +++ b/docker/dev-host/README.md @@ -0,0 +1,74 @@ +# dev-host - Auto-generated Docker Compose Template + +> ! **Auto-generated**: This directory and its contents are automatically generated by `docker/template/`. Do not edit these files directly as your changes will be overwritten. + +## Overview + +This Docker Compose configuration provides a complete development environment for Rivet with the following services: + +- **Rivet Engine**: Main orchestration service +- **Rivet Shell**: Interactive shell for debugging +- **Runner**: Executes user code +- **ClickHouse**: Analytics and time-series database +- **PostgreSQL**: Relational database +- **Vector Server**: Log aggregation and processing +- **OpenTelemetry Collector**: Observability data collection + +## Port Configuration + +| Service | Port(s) | Description | +|---------|---------|-------------| +| Rivet Engine | 6420 | Public endpoint | +| Runner | 5050 | Code execution service | +| PostgreSQL | 5432 | Database | +| ClickHouse HTTP | 9300 | Database HTTP interface | +| ClickHouse Native | 9301 | Database native protocol | +| OpenTelemetry gRPC | 4317 | OTLP gRPC endpoint | +| OpenTelemetry HTTP | 4318 | OTLP HTTP endpoint | + +## Template Configuration + +**Template Name**: `dev-host` +**Base Port**: `6420` +**Network Mode**: `host` + +### Datacenters +- **1**: 1 engine(s), 1 runner(s) + +## Usage + +1. Start all services: + ```bash + docker-compose up -d + ``` + +2. Check service health: + ```bash + docker-compose ps + ``` + +3. View logs: + ```bash + docker-compose logs -f [service-name] + ``` + +4. Stop all services: + ```bash + docker-compose down + ``` + +## Generated Files + +This template generates the following files and directories: +- `docker-compose.yml` - Main Docker Compose configuration +- `core/` - Core services shared across datacenters: + - `clickhouse/` - ClickHouse configuration and initialization + - `vector-server/` - Vector aggregator configuration + - `otel-collector-server/` - OpenTelemetry Collector server configuration +- `datacenters/` - Datacenter-specific configurations: + - `1/` - Configuration for datacenter 1: + - `postgres/` - PostgreSQL setup scripts + - `rivet-engine/` - Rivet Engine configuration + - `vector-client/` - Vector client configuration + - `otel-collector-client/` - OpenTelemetry Collector client configuration +- `README.md` - This file diff --git a/docker/dev-host/clickhouse/client-config.xml b/docker/dev-host/clickhouse/client-config.xml new file mode 100644 index 0000000000..72f9850f4e --- /dev/null +++ b/docker/dev-host/clickhouse/client-config.xml @@ -0,0 +1,5 @@ + + + 9301 + 127.0.0.1 + \ No newline at end of file diff --git a/docker/dev-host/clickhouse/config.xml b/docker/dev-host/clickhouse/config.xml new file mode 100644 index 0000000000..e7ccd0480b --- /dev/null +++ b/docker/dev-host/clickhouse/config.xml @@ -0,0 +1,52 @@ + + + + debug + /var/log/clickhouse-server/clickhouse-server.log + /var/log/clickhouse-server/clickhouse-server.err.log + 1000M + 10 + + + :: + 9300 + 9301 + + + 9440 + 9010 + + 9009 + + 4096 + 3 + 100 + 8589934592 + 5368709120 + + /var/lib/clickhouse/ + /var/lib/clickhouse/tmp/ + /var/lib/clickhouse/user_files/ + /var/lib/clickhouse/access/ + + users.xml + default + default + UTC + + + + + + 3600 + 3600 + 60 + + + system + query_log
+ 7500 +
+ + *_dictionary.xml +
diff --git a/docker/dev-host/clickhouse/init/01-create-otel-table.sql b/docker/dev-host/clickhouse/init/01-create-otel-table.sql new file mode 100644 index 0000000000..2c7b9f7957 --- /dev/null +++ b/docker/dev-host/clickhouse/init/01-create-otel-table.sql @@ -0,0 +1,107 @@ +CREATE DATABASE IF NOT EXISTS otel; + +CREATE TABLE IF NOT EXISTS otel.otel_logs ( + Timestamp DateTime64(9) CODEC(Delta, ZSTD(1)), + ObservedTimestamp DateTime64(9) CODEC(Delta, ZSTD(1)), + TraceId String CODEC(ZSTD(1)), + SpanId String CODEC(ZSTD(1)), + TraceFlags UInt32 CODEC(ZSTD(1)), + SeverityText LowCardinality(String) CODEC(ZSTD(1)), + SeverityNumber Int32 CODEC(ZSTD(1)), + ServiceName LowCardinality(String) CODEC(ZSTD(1)), + Body String CODEC(ZSTD(1)), + ResourceSchemaUrl String CODEC(ZSTD(1)), + ResourceAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ScopeSchemaUrl String CODEC(ZSTD(1)), + ScopeName String CODEC(ZSTD(1)), + ScopeVersion String CODEC(ZSTD(1)), + ScopeAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + LogAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + INDEX idx_trace_id TraceId TYPE bloom_filter(0.001) GRANULARITY 1, + INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_key mapKeys(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_value mapValues(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_log_attr_key mapKeys(LogAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_log_attr_value mapValues(LogAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_body Body TYPE tokenbf_v1(32768, 3, 0) GRANULARITY 1 +) ENGINE = MergeTree() +PARTITION BY toDate(Timestamp) +ORDER BY (ServiceName, SeverityText, toUnixTimestamp(Timestamp), TraceId) +TTL toDateTime(Timestamp) + toIntervalDay(3) +SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1; + +CREATE TABLE IF NOT EXISTS otel.otel_traces ( + Timestamp DateTime64(9) CODEC(Delta, ZSTD(1)), + TraceId String CODEC(ZSTD(1)), + SpanId String CODEC(ZSTD(1)), + ParentSpanId String CODEC(ZSTD(1)), + TraceState String CODEC(ZSTD(1)), + SpanName LowCardinality(String) CODEC(ZSTD(1)), + SpanKind LowCardinality(String) CODEC(ZSTD(1)), + ServiceName LowCardinality(String) CODEC(ZSTD(1)), + ResourceAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ScopeName String CODEC(ZSTD(1)), + ScopeVersion String CODEC(ZSTD(1)), + SpanAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + Duration Int64 CODEC(ZSTD(1)), + StatusCode LowCardinality(String) CODEC(ZSTD(1)), + StatusMessage String CODEC(ZSTD(1)), + Events Nested ( + Timestamp DateTime64(9), + Name LowCardinality(String), + Attributes Map(LowCardinality(String), String) + ) CODEC(ZSTD(1)), + Links Nested ( + TraceId String, + SpanId String, + TraceState String, + Attributes Map(LowCardinality(String), String) + ) CODEC(ZSTD(1)), + INDEX idx_trace_id TraceId TYPE bloom_filter(0.001) GRANULARITY 1, + INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_span_attr_key mapKeys(SpanAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_span_attr_value mapValues(SpanAttributes) TYPE bloom_filter(0.01) GRANULARITY 1 +) ENGINE = MergeTree() +PARTITION BY toDate(Timestamp) +ORDER BY (ServiceName, SpanName, toUnixTimestamp(Timestamp), TraceId) +TTL toDateTime(Timestamp) + toIntervalDay(7) +SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1; + +CREATE TABLE IF NOT EXISTS otel.otel_metrics ( + ResourceAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ResourceSchemaUrl String CODEC(ZSTD(1)), + ScopeName String CODEC(ZSTD(1)), + ScopeVersion String CODEC(ZSTD(1)), + ScopeAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ScopeDroppedAttrCount UInt32 CODEC(ZSTD(1)), + ScopeSchemaUrl String CODEC(ZSTD(1)), + MetricName String CODEC(ZSTD(1)), + MetricDescription String CODEC(ZSTD(1)), + MetricUnit String CODEC(ZSTD(1)), + Attributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + StartTimeUnix DateTime64(9) CODEC(Delta, ZSTD(1)), + TimeUnix DateTime64(9) CODEC(Delta, ZSTD(1)), + Value Float64 CODEC(ZSTD(1)), + Flags UInt32 CODEC(ZSTD(1)), + Exemplars Nested ( + FilteredAttributes Map(LowCardinality(String), String), + TimeUnix DateTime64(9), + Value Float64, + SpanId String, + TraceId String + ) CODEC(ZSTD(1)), + AggTemp Int32 CODEC(ZSTD(1)), + IsMonotonic Bool CODEC(ZSTD(1)), + INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_key mapKeys(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_value mapValues(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_attr_key mapKeys(Attributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_attr_value mapValues(Attributes) TYPE bloom_filter(0.01) GRANULARITY 1 +) ENGINE = MergeTree() +PARTITION BY toDate(TimeUnix) +ORDER BY (MetricName, Attributes, toUnixTimestamp(TimeUnix)) +TTL toDateTime(TimeUnix) + toIntervalDay(30) +SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1; diff --git a/docker/dev-host/clickhouse/users.xml b/docker/dev-host/clickhouse/users.xml new file mode 100644 index 0000000000..743cada261 --- /dev/null +++ b/docker/dev-host/clickhouse/users.xml @@ -0,0 +1,35 @@ + + + + + default + + ::/0 + + default + default + 1 + + + + + + 10000000000 + 0 + random + + + + + + + 3600 + 0 + 0 + 0 + 0 + 0 + + + + diff --git a/docker/dev-host/docker-compose.yml b/docker/dev-host/docker-compose.yml new file mode 100644 index 0000000000..d2555d4e77 --- /dev/null +++ b/docker/dev-host/docker-compose.yml @@ -0,0 +1,187 @@ +services: + clickhouse: + restart: unless-stopped + image: clickhouse/clickhouse-server:25.1.5 + volumes: + - clickhouse-data:/var/lib/clickhouse + - ./clickhouse/config.xml:/etc/clickhouse-server/config.d/config.xml + - ./clickhouse/users.xml:/etc/clickhouse-server/users.d/users.xml + - ./clickhouse/client-config.xml:/etc/clickhouse-client/config.xml + - ./clickhouse/init:/docker-entrypoint-initdb.d + environment: + - CLICKHOUSE_ALWAYS_RUN_INITDB_SCRIPTS=true + - CLICKHOUSE_USER=default + - CLICKHOUSE_PASSWORD=default + - CLICKHOUSE_HTTP_PORT=9300 + - CLICKHOUSE_TCP_PORT=9301 + healthcheck: + test: + - CMD + - clickhouse-client + - '--host' + - 127.0.0.1 + - '--port' + - '9301' + - '--user' + - system + - '--password' + - default + - '--query' + - SELECT 1 + interval: 2s + timeout: 10s + retries: 10 + network_mode: host + grafana: + image: grafana/grafana:11.5.2 + volumes: + - grafana-data:/var/lib/grafana + - ./grafana/grafana.ini:/etc/grafana/grafana.ini + - ./grafana/provisioning:/etc/grafana/provisioning + - ./grafana/dashboards:/var/lib/grafana/dashboards + environment: + - GF_INSTALL_PLUGINS=grafana-clickhouse-datasource + depends_on: + clickhouse: + condition: service_healthy + network_mode: host + postgres: + restart: unless-stopped + image: postgres:16-alpine + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=postgres + volumes: + - ./postgres/init-db.sh:/docker-entrypoint-initdb.d/init-db.sh + - postgres-data:/var/lib/postgresql/data + healthcheck: + test: + - CMD-SHELL + - pg_isready -U postgres -d postgres + interval: 2s + timeout: 10s + retries: 10 + network_mode: host + rivet-shell: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: sleep infinity + stop_grace_period: 0s + depends_on: + postgres: + condition: service_healthy + volumes: + - ./rivet-engine/config.jsonc:/etc/rivet/config.jsonc:ro + network_mode: host + vector-server: + restart: unless-stopped + image: timberio/vector:0.48.0-distroless-static + command: '-C /etc/vector' + volumes: + - vector-server-data-local:/var/lib/vector + - ./vector-server:/etc/vector + depends_on: + clickhouse: + condition: service_healthy + network_mode: host + vector-client: + restart: unless-stopped + image: timberio/vector:0.48.0-distroless-static + command: '-C /etc/vector' + volumes: + - vector-client-data-local:/var/lib/vector + - ./vector-client:/etc/vector + depends_on: + vector-server: + condition: service_started + network_mode: host + otel-collector-server: + image: otel/opentelemetry-collector-contrib:latest + restart: unless-stopped + command: '--config=/etc/otel/config.yaml' + volumes: + - ./otel-collector-server/config.yaml:/etc/otel/config.yaml:ro + environment: + - CLICKHOUSE_PASSWORD=default + depends_on: + clickhouse: + condition: service_healthy + network_mode: host + otel-collector-client: + image: otel/opentelemetry-collector-contrib:latest + restart: unless-stopped + command: '--config=/etc/otel/config.yaml' + volumes: + - ./otel-collector-client/config.yaml:/etc/otel/config.yaml:ro + depends_on: + otel-collector-server: + condition: service_started + network_mode: host + rivet-engine: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: /usr/bin/rivet-engine start + environment: + - RUST_LOG_ANSI_COLOR=1 + - RIVET_OTEL_ENABLED=1 + - RIVET_OTEL_SAMPLER_RATIO=1 + - RIVET_OTEL_GRPC_ENDPOINT=http://127.0.0.1:4317 + stop_grace_period: 0s + depends_on: + vector-client: + condition: service_started + otel-collector-client: + condition: service_started + postgres: + condition: service_healthy + volumes: + - ./rivet-engine/config.jsonc:/etc/rivet/config.jsonc:ro + healthcheck: + test: + - CMD + - curl + - '-f' + - http://127.0.0.1:6421/health + interval: 2s + timeout: 10s + retries: 10 + start_period: 30s + network_mode: host + runner: + build: + context: ../.. + dockerfile: sdks/typescript/test-runner/Dockerfile + platform: linux/amd64 + restart: unless-stopped + environment: + - RIVET_ENDPOINT=http://127.0.0.1:6420 + - RUNNER_HOST=127.0.0.1 + stop_grace_period: 4s + depends_on: + rivet-engine: + condition: service_healthy + network_mode: host +networks: + rivet-core-network: + driver: bridge + rivet-network: + driver: bridge + rivet-network-engine-peer: + driver: bridge + rivet-network-to-core: + driver: bridge +volumes: + clickhouse-data: null + grafana-data: null + postgres-data: null + vector-server-data-local: null + vector-client-data-local: null diff --git a/docker/dev-host/grafana/dashboards/api.json b/docker/dev-host/grafana/dashboards/api.json new file mode 100644 index 0000000000..34004bf134 --- /dev/null +++ b/docker/dev-host/grafana/dashboards/api.json @@ -0,0 +1,1172 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 7, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 24, + "panels": [], + "title": "API", + "type": "row" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 26, + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_api_request_duration'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Request Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 27, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_api_request_pending'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Requests Pending", + "transformations": [ + { + "id": "groupingToMatrix", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 10 + }, + "id": 32, + "interval": "15s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n sum(Sum) / sum(Count) as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nHAVING sum(Count) > 0\nORDER BY time", + "refId": "A" + } + ], + "title": "Duration (avg)", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 10 + }, + "id": 33, + "interval": "15s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label, bounds, idx\nORDER BY time", + "refId": "A" + } + ], + "title": "Duration (p95)", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "bounds" + } + }, + { + "id": "convertFieldType", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 16, + "y": 10 + }, + "id": 34, + "interval": "15s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n Attributes['method'] as method,\n Attributes['path'] as path,\n histogramQuantile(arrayZip(ExplicitBounds, BucketCounts), 0.99) as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND Attributes['watch'] = '0'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, method, path\nORDER BY time", + "refId": "A" + } + ], + "title": "Duration (p99)", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 19 + }, + "id": 25, + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n sum(Value) / $__interval_ms * 1000 as value\n -- (\n -- SELECT\n -- sum(Value) / $__interval_ms * 1000 as value\n -- FROM otel.otel_metrics_sum\n -- WHERE MetricName = 'rivet_api_request_total'\n -- AND $__conditionalAll(Attributes['path'], $path)\n -- AND $__conditionalAll(Attributes['method'], $method)\n -- AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n -- AND $__timeFilter(TimeUnix)\n -- ) as prev_value\n -- lagInFrame(value, 1, value) OVER (ORDER BY time) as previous_value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_api_request_total'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Request Rate", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 19 + }, + "id": 28, + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Name", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}: {{status}} ({{error_code}})", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path'], ': ',\n Attributes['status'], ' (',\n Attributes['error_code'], ')'\n ) as label,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_api_request_errors'\n AND Attributes['status'] LIKE '4%'\n AND Attributes['error_code'] NOT IN ('API_CANCELLED', 'CAPTCHA_CAPTCHA_REQUIRED')\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Error Rate (4xx)", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\label" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 16, + "y": 19 + }, + "id": 31, + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}: {{status}} ({{error_code}})", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path'], ': ',\n Attributes['error_code'], ' (',\n Attributes['status'], ')'\n ) as label,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_api_request_errors'\n AND Attributes['status'] LIKE '5%'\n AND Attributes['error_code']-- NOT IN ('API_CANCELLED', 'CAPTCHA_CAPTCHA_REQUIRED')\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Error Rate (5xx)", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "log": 2, + "type": "log" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "percent" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 28 + }, + "id": 35, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{method}} {{path}}: {{status}} {{error_code}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['method'] as method,\n Attributes['path'] as path,\n Attributes['status'] as status,\n Attributes['error_code'] as error_code,\n sum(Count) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND (Attributes['status'] = '200' OR Attributes['status'] LIKE '5%')\n AND Attributes['error_code']-- NOT IN ('API_CANCELLED', 'CAPTCHA_CAPTCHA_REQUIRED')\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, method, path, status, error_code\nORDER BY time", + "refId": "A" + } + ], + "title": "200 vs 5xx (4xx excluded)", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "30s", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request_errors' ORDER BY datacenter_id", + "includeAll": true, + "label": "Datacenter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request_errors' ORDER BY datacenter_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['path'] as path FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) ORDER BY path", + "includeAll": true, + "label": "Path", + "multi": true, + "name": "path", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['path'] as path FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) ORDER BY path", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['method'] as method FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) AND $__conditionalAll(Attributes['path'], $path) ORDER BY method", + "includeAll": true, + "label": "Method", + "multi": true, + "name": "method", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['method'] as method FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) AND $__conditionalAll(Attributes['path'], $path) ORDER BY method", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-24h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "API", + "uid": "feg8y72gpm2o0c", + "version": 1, + "weekStart": "" +} diff --git a/docker/dev-host/grafana/dashboards/cache.json b/docker/dev-host/grafana/dashboards/cache.json new file mode 100644 index 0000000000..5d762023ea --- /dev/null +++ b/docker/dev-host/grafana/dashboards/cache.json @@ -0,0 +1,1176 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 4, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 10, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n CASE\n WHEN ResourceAttributes['datacenter_id'] != '' AND ResourceAttributes['server_id'] != '' THEN concat(ResourceAttributes['datacenter_id'], ' - ', ResourceAttributes['server_id'])\n ELSE 'Route Cache Size'\n END as label,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_route_cache_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Route Cache Size", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\label" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 11, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_rate_limiter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Rate Limiters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 12, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_in_flight_counter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "In-Flight Counters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 8 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_tcp_connection_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active TCP Connections", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 8 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_tcp_connection'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "TCP Connection Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 8 + }, + "id": 1, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_tcp_connection_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "TCP Connection Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 16 + }, + "id": 7, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_proxy_request_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Proxy Requests", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 16 + }, + "id": 8, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_proxy_request'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Proxy Request Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 16 + }, + "id": 9, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_proxy_request_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Proxy Request Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 24 + }, + "id": 6, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_resolve_route_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Resolve Route Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "description": "", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "description": "", + "includeAll": true, + "label": "Dataceter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "description": "", + "includeAll": true, + "label": "Server ID", + "multi": true, + "name": "server_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Rivet Guard", + "uid": "cen785ige8fswd", + "version": 1, + "weekStart": "" +} diff --git a/docker/dev-host/grafana/dashboards/futures.json b/docker/dev-host/grafana/dashboards/futures.json new file mode 100644 index 0000000000..0c992c4bcb --- /dev/null +++ b/docker/dev-host/grafana/dashboards/futures.json @@ -0,0 +1,208 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_instrumented_future_duration'\n AND $__conditionalAll(Attributes['name'], $name)\n AND $__conditionalAll(Attributes['location'], $location)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Instrumented Future Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "30s", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['name'] as name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY name", + "includeAll": true, + "label": "Name", + "multi": true, + "name": "name", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['name'] as name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY name", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['location'] as location FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY location", + "includeAll": true, + "label": "Location", + "multi": true, + "name": "location", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['location'] as location FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY location", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Futures", + "version": 0, + "weekStart": "" +} \ No newline at end of file diff --git a/docker/dev-host/grafana/dashboards/gasoline.json b/docker/dev-host/grafana/dashboards/gasoline.json new file mode 100644 index 0000000000..bac8c7b6da --- /dev/null +++ b/docker/dev-host/grafana/dashboards/gasoline.json @@ -0,0 +1,2583 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": 3, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{workflow_name}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_active'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Running Workflows", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 3, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{workflow_name}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_sleeping'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Sleeping Workflows", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 1, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{workflow_name}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_dead'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Dead Workflows", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 6, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "({{workflow_name}}) {{error_code}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n Attributes['error_code'] as error_code,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_dead'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name, error_code\nORDER BY time", + "refId": "A" + } + ], + "title": "Dead Workflow Errors", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "__auto", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n count(*) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_worker_last_ping'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Workers", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "datacenter_id", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\datacenter_id" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 4, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{signal_name}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['signal_name'] as signal_name,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_signal_pending'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, signal_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Pending Signals", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "signal_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\signal_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 10, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size", + "value": "" + }, + "yBuckets": { + "mode": "size", + "scale": { + "log": 2, + "type": "log" + }, + "value": "" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "hide": false, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_signal_recv_lag'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Signal Receive Lag", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 24 + }, + "id": 11, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_signal_pull_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY\n Time, le\nORDER BY\n Time, le", + "refId": "A" + } + ], + "title": "Pull Signals Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 32 + }, + "id": 13, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "instant": false, + "legendFormat": "{{worker_instance_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['worker_instance_id'] as worker_instance_id,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_last_pull_workflows_duration'\n AND ResourceAttributes['cluster_id'] LIKE '${cluster_id:regex}'\n AND ResourceAttributes['datacenter_id'] LIKE '${datacenter_id:regex}'\n AND $__timeFilter(TimeUnix)\nGROUP BY time, worker_instance_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Last Pull Workflows Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "worker_instance_id", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\worker_instance_id" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 32 + }, + "id": 14, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "instant": false, + "legendFormat": "{{worker_instance_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['worker_instance_id'] as worker_instance_id,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_last_pull_workflows_history_duration'\n AND ResourceAttributes['cluster_id'] LIKE '${cluster_id:regex}'\n AND ResourceAttributes['datacenter_id'] LIKE '${datacenter_id:regex}'\n AND $__timeFilter(TimeUnix)\nGROUP BY time, worker_instance_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Last Pull Workflows History Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "worker_instance_id", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\worker_instance_id" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 40 + }, + "id": 23, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_pull_workflows_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Pull Workflows Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 40 + }, + "id": 24, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_pull_workflows_history_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Pull Workflows History Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 48 + }, + "id": 16, + "panels": [], + "title": "Steps", + "type": "row" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 49 + }, + "id": 12, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_activity_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Activity Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 49 + }, + "id": 9, + "interval": "15s", + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{activity_name}}: {{error_code}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['activity_name'] as activity_name,\n Attributes['error_code'] as error_code,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_gasoline_activity_errors'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, activity_name, error_code\nORDER BY time", + "refId": "A" + } + ], + "title": "Activity Error Rate", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "activity_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\activity_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 58 + }, + "id": 21, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_loop_iteration_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Loop Upsert Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ev/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 58 + }, + "id": 25, + "interval": "15s", + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "legendFormat": "{{workflow_name}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n sum(Count) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_gasoline_loop_iteration_duration'\n AND Attributes['workflow_name'] LIKE '${workflow_name:regex}'\n AND ResourceAttributes['cluster_id'] LIKE '${cluster_id:regex}'\n AND ResourceAttributes['datacenter_id'] LIKE '${datacenter_id:regex}'\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Loop Events Per Second", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 67 + }, + "id": 17, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_message_send_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Message Send Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 67 + }, + "id": 20, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_signal_send_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Signal Send Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 76 + }, + "id": 22, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_find_workflows_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Find Workflows Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 76 + }, + "id": 19, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_workflow_dispatch_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Sub Workflow Dispatch Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "5s", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY cluster_id", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY cluster_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY datacenter_id", + "includeAll": true, + "label": "Datacenter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY datacenter_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['workflow_name'] as workflow_name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_gasoline_signal_recv_lag' ORDER BY workflow_name", + "includeAll": true, + "label": "Workflow Name", + "multi": true, + "name": "workflow_name", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['workflow_name'] as workflow_name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_gasoline_signal_recv_lag' ORDER BY workflow_name", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Gasoline", + "uid": "636d22f9-d18f-4086-8b45-7c50886a105c", + "version": 1, + "weekStart": "" +} diff --git a/docker/dev-host/grafana/dashboards/guard.json b/docker/dev-host/grafana/dashboards/guard.json new file mode 100644 index 0000000000..fb657d441b --- /dev/null +++ b/docker/dev-host/grafana/dashboards/guard.json @@ -0,0 +1,1150 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 115, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 10, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_route_cache_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Route Cache Size", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 11, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_rate_limiter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Rate Limiters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 12, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_in_flight_counter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "In-Flight Counters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 8 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_tcp_connection_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active TCP Connections", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 8 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_tcp_connection'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "TCP Connection Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 8 + }, + "id": 1, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_tcp_connection_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "TCP Connection Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 16 + }, + "id": 7, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_proxy_request_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Proxy Requests", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 16 + }, + "id": 8, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_proxy_request'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Proxy Request Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 16 + }, + "id": 9, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_proxy_request_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Proxy Request Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 24 + }, + "id": 6, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_resolve_route_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Resolve Route Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "description": "", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "description": "", + "includeAll": true, + "label": "Dataceter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "description": "", + "includeAll": true, + "label": "Server ID", + "multi": true, + "name": "server_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Rivet Guard", + "uid": "cen785ige8fswd", + "version": 1, + "weekStart": "" +} diff --git a/docker/dev-host/grafana/dashboards/tokio.json b/docker/dev-host/grafana/dashboards/tokio.json new file mode 100644 index 0000000000..efa5e4b49f --- /dev/null +++ b/docker/dev-host/grafana/dashboards/tokio.json @@ -0,0 +1,1009 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": 81, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 24, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_global_queue_depth'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Global Queue Depth", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 27, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_worker_local_queue_depth'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Worker Queue Depth", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 11, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_tokio_task_poll_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Task Poll Times", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 26, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_worker_overflow_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Worker Overflow Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 23, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_future_schedule_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Future Schedule Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 25, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_thread_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Thread Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "tasks/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 28, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_tokio_task'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Task Spawn Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 24 + }, + "id": 29, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_active_task_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Tasks", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "5s", + "schemaVersion": 40, + "templating": { + "list": [ + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY cluster_id", + "description": "", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY cluster_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY datacenter_id", + "description": "", + "includeAll": true, + "label": "Dataceter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY datacenter_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY server_id", + "description": "", + "includeAll": true, + "label": "Server ID", + "multi": true, + "name": "server_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY server_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['pool_type'] as pool_type FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY pool_type", + "includeAll": true, + "label": "Pool", + "multi": true, + "name": "pool_type", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['pool_type'] as pool_type FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY pool_type", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Tokio", + "uid": "636d22f9-d18f-4086-8b45-7c50886a105d", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/docker/dev-host/grafana/dashboards/traces.json b/docker/dev-host/grafana/dashboards/traces.json new file mode 100644 index 0000000000..64f6b552c9 --- /dev/null +++ b/docker/dev-host/grafana/dashboards/traces.json @@ -0,0 +1,979 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 21, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 9, + "panels": [], + "title": "Traces", + "type": "row" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "bars", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 0, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 1 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-traces" + }, + "editorType": "sql", + "format": 0, + "meta": { + "builderOptions": { + "aggregates": [ + { + "aggregateType": "count", + "column": "" + } + ], + "columns": [ + { + "hint": "time", + "name": "Timestamp", + "type": "DateTime64(9)" + } + ], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "hint": "time", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "ServiceName" + ], + "limit": 10000, + "mode": "trend", + "orderBy": [], + "queryType": "timeseries", + "table": "otel_traces" + } + }, + "pluginVersion": "4.0.6", + "queryType": "timeseries", + "rawSql": "SELECT\r\n $__timeInterval(Timestamp) as time,\r\n ServiceName,\r\n count() as ` `\r\nFROM otel.otel_traces\r\nWHERE\r\n ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )\r\n AND $__conditionalAll(ServiceName, $service_name)\r\n AND $__conditionalAll(SpanName, $span_name)\r\n AND (($ray_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['ray_id'], $ray_id))\r\n AND (($workflow_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['workflow_id'], $workflow_id))\r\nGROUP BY ServiceName, time\r\nORDER BY time ASC\r\nLIMIT 100000\r\n", + "refId": "A" + } + ], + "title": "Traces per Service", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Trace ID" + }, + "properties": [ + { + "id": "custom.width", + "value": 77 + }, + { + "id": "links", + "value": [ + { + "title": "__value.raw", + "url": "/d/8klBUGfVk/otel-traces?${__url_time_range}&${service_name:queryparam}&var-trace_id=${__value.raw}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Service Name" + }, + "properties": [ + { + "id": "custom.width", + "value": 130 + }, + { + "id": "links", + "value": [ + { + "title": "__value.raw", + "url": "/d/8klBUGfVk/otel-traces?${__url_time_range}&${trace_id:queryparam}&var-serviceName=${__value.raw}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Duration" + }, + "properties": [ + { + "id": "unit", + "value": "ms" + }, + { + "id": "custom.cellOptions", + "value": { + "mode": "lcd", + "type": "gauge", + "valueDisplayMode": "text" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "timestamp" + }, + "properties": [ + { + "id": "custom.width", + "value": 216 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Service Tags" + }, + "properties": [ + { + "id": "custom.inspect", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "timestamp" + }, + "properties": [ + { + "id": "custom.width", + "value": 248 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "timestamp" + }, + "properties": [ + { + "id": "custom.width", + "value": 234 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": " " + }, + "properties": [ + { + "id": "custom.width", + "value": 49 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Span Name" + }, + "properties": [ + { + "id": "custom.width", + "value": 140 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Ts" + }, + "properties": [ + { + "id": "custom.width", + "value": 168 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "URI/workflow_id/actor_id" + }, + "properties": [ + { + "id": "custom.width", + "value": 920 + } + ] + } + ] + }, + "gridPos": { + "h": 13, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 4, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Duration" + } + ] + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorType": "sql", + "format": 1, + "meta": { + "builderOptions": { + "columns": [], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "queryType": "table", + "table": "otel_traces" + } + }, + "pluginVersion": "4.9.0", + "queryType": "table", + "rawSql": "SELECT\r\n (argMin(StatusCode, Timestamp) = 'Error' ? '⚠️' : '') as ` `,\r\n min(Timestamp) as Ts,\r\n TraceId as `Trace ID`,\r\n argMin(ServiceName, Timestamp) as `Service Name`,\r\n argMin(SpanName, Timestamp) as `Span Name`,\r\n argMin(coalesce(NULLIF(SpanAttributes['uri'], ''), NULLIF(SpanAttributes['workflow_id'], ''), SpanAttributes['actor_id']), Timestamp) as `URI/workflow_id/actor_id`,\r\n divide(max(Duration), 1000000) as Duration\r\nFROM otel.otel_traces\r\nWHERE\r\n $__conditionalAll(ServiceName, $service_name)\r\n AND $__conditionalAll(SpanName, $span_name)\r\n AND (($ray_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['ray_id'], $ray_id))\r\n AND (($workflow_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['workflow_id'], $workflow_id))\r\n AND ServiceName != 'loadgenerator'\r\n AND ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )\r\nGROUP BY TraceId\r\nORDER BY Duration DESC\r\nLIMIT 100\r\n", + "refId": "A" + } + ], + "title": "Traces", + "type": "table" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, + "gridPos": { + "h": 17, + "w": 24, + "x": 0, + "y": 23 + }, + "id": 6, + "options": { + "spanFilters": { + "criticalPathOnly": false, + "matchesOnly": false, + "serviceNameOperator": "=", + "spanNameOperator": "=" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "builderOptions": { + "columns": [ + { + "hint": "trace_id", + "name": "TraceId" + }, + { + "hint": "trace_span_id", + "name": "SpanId" + }, + { + "hint": "trace_parent_span_id", + "name": "ParentSpanId" + }, + { + "hint": "trace_service_name", + "name": "ServiceName" + }, + { + "hint": "trace_operation_name", + "name": "SpanName" + }, + { + "hint": "time", + "name": "Timestamp" + }, + { + "hint": "trace_duration_time", + "name": "Duration" + }, + { + "hint": "trace_tags", + "name": "SpanAttributes" + }, + { + "hint": "trace_service_tags", + "name": "ResourceAttributes" + }, + { + "hint": "trace_status_code", + "name": "StatusCode" + } + ], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "hint": "time", + "key": "", + "operator": "WITH IN DASHBOARD TIME RANGE", + "type": "datetime" + }, + { + "condition": "AND", + "filterType": "custom", + "hint": "trace_duration_time", + "key": "", + "operator": ">", + "type": "UInt64", + "value": 0 + }, + { + "condition": "AND", + "filterType": "custom", + "hint": "trace_service_name", + "key": "", + "operator": "IS ANYTHING", + "type": "string", + "value": "" + } + ], + "limit": 1000, + "meta": { + "isTraceIdMode": true, + "otelEnabled": true, + "otelVersion": "latest", + "traceDurationUnit": "nanoseconds", + "traceId": "${trace_id}" + }, + "mode": "list", + "orderBy": [ + { + "default": true, + "dir": "DESC", + "hint": "time", + "name": "" + }, + { + "default": true, + "dir": "DESC", + "hint": "trace_duration_time", + "name": "" + } + ], + "queryType": "traces", + "table": "otel_traces" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-traces" + }, + "editorType": "builder", + "format": 3, + "meta": { + "builderOptions": { + "columns": [], + "database": "", + "limit": 100, + "mode": "list", + "queryType": "table", + "table": "" + } + }, + "pluginVersion": "4.0.6", + "queryType": "traces", + "rawSql": "WITH\n\t(SELECT min(Start) FROM otel.otel_traces_trace_id_ts WHERE $__conditionalAll(TraceId, $trace_id)) as trace_start,\n\t(SELECT max(End) + 1 FROM otel.otel_traces_trace_id_ts WHERE $__conditionalAll(TraceId, $trace_id)) as trace_end\nSELECT\n\tTraceId as traceID,\n\tSpanId as spanID,\n\tParentSpanId as parentSpanID,\n\tServiceName as serviceName,\n\tSpanName as operationName, Timestamp as startTime,\n\tmultiply(Duration, 0.000001) as duration,\n\tarrayMap(key -> map('key', key, 'value', SpanAttributes[key]), mapKeys(SpanAttributes)) as tags,\n\tarrayMap(key -> map('key', key, 'value', ResourceAttributes[key]), mapKeys(ResourceAttributes)) as serviceTags,\n\tarrayMap((name, timestamp, attributes) -> tuple(name, toString(multiply(toUnixTimestamp64Nano(timestamp), 0.000001)), arrayMap( key -> map('key', key, 'value', attributes[key]), mapKeys(attributes)))::Tuple(name String, timestamp String, fields Array(Map(String, String))), `Events.Name`, `Events.Timestamp`, `Events.Attributes`) AS logs,\n\tarrayMap((traceID, spanID, attributes) -> tuple(traceID, spanID, arrayMap(key -> map('key', key, 'value', attributes[key]), mapKeys(attributes)))::Tuple(traceID String, spanID String, tags Array(Map(String, String))), `Links.TraceId`, `Links.SpanId`, `Links.Attributes`) AS references\nFROM otel.otel_traces\nWHERE\n\t$__conditionalAll(traceID, $trace_id) AND startTime >= trace_start AND startTime <= trace_end AND ( Duration > 0 )\nORDER BY Timestamp DESC, Duration DESC\nLIMIT 1000", + "refId": "A" + } + ], + "title": "Trace Details", + "type": "traces" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "bars", + "fillOpacity": 24, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 8, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-traces" + }, + "editorType": "sql", + "format": 0, + "meta": { + "builderOptions": { + "aggregates": [ + { + "aggregateType": "count", + "column": "" + } + ], + "columns": [ + { + "hint": "time", + "name": "Timestamp", + "type": "DateTime64(9)" + } + ], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "hint": "time", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "ServiceName" + ], + "limit": 10000, + "mode": "trend", + "orderBy": [], + "queryType": "timeseries", + "table": "otel_traces" + } + }, + "pluginVersion": "4.0.6", + "queryType": "timeseries", + "rawSql": "SELECT\r\n $__timeInterval(Timestamp) as time,\r\n count(*) as ` `,\r\n ServiceName\r\nFROM otel.otel_traces\r\nWHERE\r\n $__conditionalAll(TraceId, $trace_id)\r\n AND ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )\r\n AND $__conditionalAll(ServiceName, $service_name)\r\n AND $__conditionalAll(SpanName, $span_name)\r\n AND (($ray_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['ray_id'], $ray_id)\r\n AND (($workflow_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['workflow_id'], $workflow_id))\r\n AND StatusCode IN ('Error', 'STATUS_CODE_ERROR')\r\n AND ServiceName != 'loadgenerator' GROUP BY ServiceName, time\r\nORDER BY time ASC\r\nLIMIT 100000", + "refId": "A" + } + ], + "title": "Error rates", + "type": "timeseries" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 49 + }, + "id": 10, + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 61 + }, + "id": 11, + "options": { + "dedupStrategy": "none", + "enableInfiniteScrolling": false, + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": true, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "builderOptions": { + "columns": [ + { + "hint": "time", + "name": "Timestamp", + "type": "DateTime64(9)" + }, + { + "hint": "log_level", + "name": "SeverityText", + "type": "LowCardinality(String)" + }, + { + "hint": "log_message", + "name": "Body", + "type": "String" + } + ], + "database": "otel", + "filters": [], + "limit": 1000, + "meta": { + "logMessageLike": "", + "otelVersion": "latest" + }, + "mode": "list", + "orderBy": [], + "queryType": "logs", + "table": "otel_logs" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorType": "builder", + "format": 2, + "pluginVersion": "4.0.6", + "rawSql": "SELECT Timestamp as timestamp, Body as body, SeverityText as level FROM \"otel\".\"otel_logs\" LIMIT 1000", + "refId": "A" + } + ], + "title": "Trace Logs", + "type": "logs" + } + ], + "title": "Logs", + "type": "row" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "ClickHouse", + "value": "ClickHouse" + }, + "includeAll": false, + "label": "ClickHouse instance", + "name": "datasource", + "options": [], + "query": "grafana-clickhouse-datasource", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ServiceName FROM otel.otel_traces", + "includeAll": true, + "label": "Service Name", + "multi": true, + "name": "service_name", + "options": [], + "query": "SELECT DISTINCT ServiceName FROM otel.otel_traces", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT TraceId FROM otel.otel_traces WHERE ParentSpanId = '' LIMIT 100", + "includeAll": true, + "label": "Trace ID", + "name": "trace_id", + "options": [], + "query": "SELECT DISTINCT TraceId FROM otel.otel_traces WHERE ParentSpanId = '' LIMIT 100", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT SpanName FROM otel.otel_traces WHERE $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "description": "", + "includeAll": true, + "label": "Span", + "multi": true, + "name": "span_name", + "options": [], + "query": "SELECT DISTINCT SpanName FROM otel.otel_traces WHERE $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "allValue": "'All'", + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT SpanAttributes['ray_id'] FROM otel.otel_traces WHERE SpanAttributes['ray_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "description": "", + "includeAll": true, + "label": "Ray ID", + "multi": true, + "name": "ray_id", + "options": [], + "query": "SELECT DISTINCT SpanAttributes['ray_id'] FROM otel.otel_traces WHERE SpanAttributes['ray_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "allValue": "'All'", + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT SpanAttributes['workflow_id'] FROM otel.otel_traces WHERE SpanAttributes['workflow_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "description": "", + "includeAll": true, + "label": "Workflow ID", + "multi": true, + "name": "workflow_id", + "options": [], + "query": "SELECT DISTINCT SpanAttributes['workflow_id'] FROM otel.otel_traces WHERE SpanAttributes['workflow_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "America/Los_Angeles", + "title": "Traces", + "uid": "8klBUGfVk", + "version": 2, + "weekStart": "" +} diff --git a/docker/dev-host/grafana/grafana.ini b/docker/dev-host/grafana/grafana.ini new file mode 100644 index 0000000000..1bd9bfe697 --- /dev/null +++ b/docker/dev-host/grafana/grafana.ini @@ -0,0 +1,14 @@ +[server] +http_port = 3000 +root_url = http://localhost:3100 + +[security] +admin_user = admin +admin_password = admin + +[auth.anonymous] +enabled = true +org_role = Viewer + +[dashboards] +default_home_dashboard_path = /var/lib/grafana/dashboards/api.json diff --git a/docker/dev-host/grafana/provisioning/dashboards/dashboards.yaml b/docker/dev-host/grafana/provisioning/dashboards/dashboards.yaml new file mode 100644 index 0000000000..7d91589dc7 --- /dev/null +++ b/docker/dev-host/grafana/provisioning/dashboards/dashboards.yaml @@ -0,0 +1,10 @@ +apiVersion: 1 +providers: + - name: rivet-dashboards + orgId: 1 + folder: '' + type: file + disableDeletion: false + updateIntervalSeconds: 10 + options: + path: /var/lib/grafana/dashboards diff --git a/docker/dev-host/grafana/provisioning/datasources/datasources.yaml b/docker/dev-host/grafana/provisioning/datasources/datasources.yaml new file mode 100644 index 0000000000..3cc84bfbfb --- /dev/null +++ b/docker/dev-host/grafana/provisioning/datasources/datasources.yaml @@ -0,0 +1,30 @@ +apiVersion: 1 +datasources: + - name: ClickHouse + uid: clickhouse + type: grafana-clickhouse-datasource + access: proxy + secureJsonData: + password: default + jsonData: + version: 2.0.0 + host: 127.0.0.1 + port: 9300 + defaultDatabase: default + protocol: http + secure: false + username: default + validateSql: true + logs: + otelEnabled: true + otelVersion: 1.2.9 + defaultDatabase: otel + defaultTable: otel_logs + timeColumn: TimestampTime + messageColumn: Body + levelColumn: SeverityText + traces: + otelEnabled: true + otelVersion: 1.2.9 + defaultDatabase: otel + defaultTable: otel_traces diff --git a/docker/dev-host/otel-collector-client/config.yaml b/docker/dev-host/otel-collector-client/config.yaml new file mode 100644 index 0000000000..444a77a7af --- /dev/null +++ b/docker/dev-host/otel-collector-client/config.yaml @@ -0,0 +1,39 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + http: + endpoint: 0.0.0.0:4318 +processors: + batch: + timeout: 5s + send_batch_size: 10000 +exporters: + otlp/server: + endpoint: 127.0.0.1:4317 + tls: + insecure: true +service: + pipelines: + logs: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server + traces: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server + metrics: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server diff --git a/docker/dev-host/otel-collector-server/config.yaml b/docker/dev-host/otel-collector-server/config.yaml new file mode 100644 index 0000000000..15f12073f0 --- /dev/null +++ b/docker/dev-host/otel-collector-server/config.yaml @@ -0,0 +1,61 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 +processors: + batch: + timeout: 5s + send_batch_size: 10000 +exporters: + clickhouse: + endpoint: http://127.0.0.1:9300 + database: otel + username: default + password: ${env:CLICKHOUSE_PASSWORD} + async_insert: true + ttl: 72h + compress: lz4 + create_schema: true + logs_table_name: otel_logs + traces_table_name: otel_traces + timeout: 5s + metrics_tables: + gauge: + name: otel_metrics_gauge + sum: + name: otel_metrics_sum + summary: + name: otel_metrics_summary + histogram: + name: otel_metrics_histogram + exponential_histogram: + name: otel_metrics_exp_histogram + retry_on_failure: + enabled: true + initial_interval: 5s + max_interval: 30s + max_elapsed_time: 300s +service: + pipelines: + logs: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse + traces: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse + metrics: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse diff --git a/docker/dev-host/postgres/init-db.sh b/docker/dev-host/postgres/init-db.sh new file mode 100755 index 0000000000..6b57fcfef7 --- /dev/null +++ b/docker/dev-host/postgres/init-db.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -e + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + CREATE DATABASE rivet_engine; +EOSQL diff --git a/docker/dev-host/rivet-engine/config.jsonc b/docker/dev-host/rivet-engine/config.jsonc new file mode 100644 index 0000000000..de62c69aa5 --- /dev/null +++ b/docker/dev-host/rivet-engine/config.jsonc @@ -0,0 +1,56 @@ +{ + "guard": { + "port": 6420 + }, + "api_public": { + "lan_host": "127.0.0.1", + "host": "0.0.0.0", + "port": 6421 + }, + "api_peer": { + "host": "0.0.0.0", + "port": 6422 + }, + "pegboard": { + "lan_host": "127.0.0.1", + "host": "0.0.0.0", + "port": 6423 + }, + "logs": {}, + "topology": { + "datacenter_label": 1, + "datacenters": [ + { + "name": "local", + "datacenter_label": 1, + "is_leader": true, + "api_peer_url": "http://127.0.0.1:6422", + "guard_url": "http://127.0.0.1:6420" + } + ] + }, + "postgres": { + "url": "postgresql://postgres:postgres@127.0.0.1:5432/rivet_engine" + }, + "cache": { + "driver": "in_memory" + }, + "clickhouse": { + "http_url": "http://127.0.0.1:9300", + "native_url": "http://127.0.0.1:9301", + "username": "system", + "password": "default", + "provision_users": { + "vector": { + "username": "vector", + "password": "vector", + "role": "write" + } + }, + "secure": false + }, + "vector_http": { + "host": "127.0.0.1", + "port": 5022 + } +} \ No newline at end of file diff --git a/docker/dev-host/vector-client/vector.yaml b/docker/dev-host/vector-client/vector.yaml new file mode 100644 index 0000000000..88737543f8 --- /dev/null +++ b/docker/dev-host/vector-client/vector.yaml @@ -0,0 +1,31 @@ +# Vector Client Configuration for Datacenter: local +# This Vector instance runs on each server to collect local logs and forward them +# to the central Vector server aggregator. + +api: + enabled: true + address: 0.0.0.0:8686 +sources: + http_events: + type: http_server + address: 0.0.0.0:5022 + encoding: ndjson +transforms: {} +sinks: + vector_server: + type: vector + inputs: + - http_events + address: 127.0.0.1:6000 + version: '2' + buffer: + type: disk + max_size: 2147483648 + when_full: block + console_debug: + type: console + inputs: + - http_events + encoding: + codec: json + \ No newline at end of file diff --git a/docker/dev-host/vector-server/vector.yaml b/docker/dev-host/vector-server/vector.yaml new file mode 100644 index 0000000000..2294595ddd --- /dev/null +++ b/docker/dev-host/vector-server/vector.yaml @@ -0,0 +1,61 @@ +# Vector Server (Aggregator) Configuration +# This Vector instance acts as an aggregator that collects logs and metrics from all Vector clients +# across different datacenters and forwards them to ClickHouse and other sinks. + +api: + enabled: true + address: 0.0.0.0:8686 +sources: + vector: + type: vector + address: 0.0.0.0:6000 + version: '2' + tcp_json: + type: socket + mode: tcp + address: 0.0.0.0:6100 + decoding: + codec: json + http_json: + type: http_server + address: 0.0.0.0:6200 + encoding: json + vector_metrics: + type: internal_metrics + vector_logs: + type: internal_logs +transforms: + clickhouse_dynamic_events_filter: + type: filter + inputs: + - vector + condition: + type: vrl + source: .source == "clickhouse" + clickhouse_dynamic_events_transform: + type: remap + inputs: + - clickhouse_dynamic_events_filter + source: "# Extract and store metadata\n__database = .database\n__table = .table\n__columns = .columns\n\n# Create a new object with just the columns data\n. = {\n\t\"__database\": __database,\n\t\"__table\": __table,\n\t# By default insert namespace column since most tables include this\n\t\"namespace\": \"rivet\"\n}\n\t\n# Merge in the column data that should be inserted\n. = merge!(., __columns)\n" +sinks: + clickhouse_dynamic_events: + type: clickhouse + inputs: + - clickhouse_dynamic_events_transform + endpoint: http://127.0.0.1:9300 + database: '{{ __database }}' + table: '{{ __table }}' + compression: gzip + auth: + strategy: basic + user: system + password: default + batch: + max_events: 1000 + timeout_secs: 10 + console_vector_logs: + type: console + inputs: + - vector_logs + encoding: + codec: json diff --git a/docker/dev-multidc-multinode/.gitattributes b/docker/dev-multidc-multinode/.gitattributes new file mode 100644 index 0000000000..447edeb5c2 --- /dev/null +++ b/docker/dev-multidc-multinode/.gitattributes @@ -0,0 +1 @@ +. linguist-generated=true diff --git a/docker/dev-multidc-multinode/README.md b/docker/dev-multidc-multinode/README.md new file mode 100644 index 0000000000..3ff2edf0eb --- /dev/null +++ b/docker/dev-multidc-multinode/README.md @@ -0,0 +1,86 @@ +# dev-multidc-multinode - Auto-generated Docker Compose Template + +> ! **Auto-generated**: This directory and its contents are automatically generated by `docker/template/`. Do not edit these files directly as your changes will be overwritten. + +## Overview + +This Docker Compose configuration provides a complete development environment for Rivet with the following services: + +- **Rivet Engine**: Main orchestration service +- **Rivet Shell**: Interactive shell for debugging +- **Runner**: Executes user code +- **ClickHouse**: Analytics and time-series database +- **PostgreSQL**: Relational database +- **Vector Server**: Log aggregation and processing +- **OpenTelemetry Collector**: Observability data collection + +## Port Configuration + +| Service | Port(s) | Description | +|---------|---------|-------------| +| Rivet Engine | 6420 | Public endpoint | +| Runner | 5050 | Code execution service | +| PostgreSQL | 5432 | Database | +| ClickHouse HTTP | 9300 | Database HTTP interface | +| ClickHouse Native | 9301 | Database native protocol | +| OpenTelemetry gRPC | 4317 | OTLP gRPC endpoint | +| OpenTelemetry HTTP | 4318 | OTLP HTTP endpoint | + +## Template Configuration + +**Template Name**: `dev-multidc-multinode` +**Base Port**: `6420` +**Network Mode**: `bridge` + +### Datacenters +- **1**: 3 engine(s), 3 runner(s) +- **2**: 3 engine(s), 3 runner(s) +- **3**: 3 engine(s), 3 runner(s) + +## Usage + +1. Start all services: + ```bash + docker-compose up -d + ``` + +2. Check service health: + ```bash + docker-compose ps + ``` + +3. View logs: + ```bash + docker-compose logs -f [service-name] + ``` + +4. Stop all services: + ```bash + docker-compose down + ``` + +## Generated Files + +This template generates the following files and directories: +- `docker-compose.yml` - Main Docker Compose configuration +- `core/` - Core services shared across datacenters: + - `clickhouse/` - ClickHouse configuration and initialization + - `vector-server/` - Vector aggregator configuration + - `otel-collector-server/` - OpenTelemetry Collector server configuration +- `datacenters/` - Datacenter-specific configurations: + - `1/` - Configuration for datacenter 1: + - `postgres/` - PostgreSQL setup scripts + - `rivet-engine/` - Rivet Engine configuration + - `vector-client/` - Vector client configuration + - `otel-collector-client/` - OpenTelemetry Collector client configuration + - `2/` - Configuration for datacenter 2: + - `postgres/` - PostgreSQL setup scripts + - `rivet-engine/` - Rivet Engine configuration + - `vector-client/` - Vector client configuration + - `otel-collector-client/` - OpenTelemetry Collector client configuration + - `3/` - Configuration for datacenter 3: + - `postgres/` - PostgreSQL setup scripts + - `rivet-engine/` - Rivet Engine configuration + - `vector-client/` - Vector client configuration + - `otel-collector-client/` - OpenTelemetry Collector client configuration +- `README.md` - This file diff --git a/docker/dev-multidc-multinode/core/clickhouse/client-config.xml b/docker/dev-multidc-multinode/core/clickhouse/client-config.xml new file mode 100644 index 0000000000..72f9850f4e --- /dev/null +++ b/docker/dev-multidc-multinode/core/clickhouse/client-config.xml @@ -0,0 +1,5 @@ + + + 9301 + 127.0.0.1 + \ No newline at end of file diff --git a/docker/dev-multidc-multinode/core/clickhouse/config.xml b/docker/dev-multidc-multinode/core/clickhouse/config.xml new file mode 100644 index 0000000000..e7ccd0480b --- /dev/null +++ b/docker/dev-multidc-multinode/core/clickhouse/config.xml @@ -0,0 +1,52 @@ + + + + debug + /var/log/clickhouse-server/clickhouse-server.log + /var/log/clickhouse-server/clickhouse-server.err.log + 1000M + 10 + + + :: + 9300 + 9301 + + + 9440 + 9010 + + 9009 + + 4096 + 3 + 100 + 8589934592 + 5368709120 + + /var/lib/clickhouse/ + /var/lib/clickhouse/tmp/ + /var/lib/clickhouse/user_files/ + /var/lib/clickhouse/access/ + + users.xml + default + default + UTC + + + + + + 3600 + 3600 + 60 + + + system + query_log
+ 7500 +
+ + *_dictionary.xml +
diff --git a/docker/dev-multidc-multinode/core/clickhouse/init/01-create-otel-table.sql b/docker/dev-multidc-multinode/core/clickhouse/init/01-create-otel-table.sql new file mode 100644 index 0000000000..2c7b9f7957 --- /dev/null +++ b/docker/dev-multidc-multinode/core/clickhouse/init/01-create-otel-table.sql @@ -0,0 +1,107 @@ +CREATE DATABASE IF NOT EXISTS otel; + +CREATE TABLE IF NOT EXISTS otel.otel_logs ( + Timestamp DateTime64(9) CODEC(Delta, ZSTD(1)), + ObservedTimestamp DateTime64(9) CODEC(Delta, ZSTD(1)), + TraceId String CODEC(ZSTD(1)), + SpanId String CODEC(ZSTD(1)), + TraceFlags UInt32 CODEC(ZSTD(1)), + SeverityText LowCardinality(String) CODEC(ZSTD(1)), + SeverityNumber Int32 CODEC(ZSTD(1)), + ServiceName LowCardinality(String) CODEC(ZSTD(1)), + Body String CODEC(ZSTD(1)), + ResourceSchemaUrl String CODEC(ZSTD(1)), + ResourceAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ScopeSchemaUrl String CODEC(ZSTD(1)), + ScopeName String CODEC(ZSTD(1)), + ScopeVersion String CODEC(ZSTD(1)), + ScopeAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + LogAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + INDEX idx_trace_id TraceId TYPE bloom_filter(0.001) GRANULARITY 1, + INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_key mapKeys(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_value mapValues(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_log_attr_key mapKeys(LogAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_log_attr_value mapValues(LogAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_body Body TYPE tokenbf_v1(32768, 3, 0) GRANULARITY 1 +) ENGINE = MergeTree() +PARTITION BY toDate(Timestamp) +ORDER BY (ServiceName, SeverityText, toUnixTimestamp(Timestamp), TraceId) +TTL toDateTime(Timestamp) + toIntervalDay(3) +SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1; + +CREATE TABLE IF NOT EXISTS otel.otel_traces ( + Timestamp DateTime64(9) CODEC(Delta, ZSTD(1)), + TraceId String CODEC(ZSTD(1)), + SpanId String CODEC(ZSTD(1)), + ParentSpanId String CODEC(ZSTD(1)), + TraceState String CODEC(ZSTD(1)), + SpanName LowCardinality(String) CODEC(ZSTD(1)), + SpanKind LowCardinality(String) CODEC(ZSTD(1)), + ServiceName LowCardinality(String) CODEC(ZSTD(1)), + ResourceAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ScopeName String CODEC(ZSTD(1)), + ScopeVersion String CODEC(ZSTD(1)), + SpanAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + Duration Int64 CODEC(ZSTD(1)), + StatusCode LowCardinality(String) CODEC(ZSTD(1)), + StatusMessage String CODEC(ZSTD(1)), + Events Nested ( + Timestamp DateTime64(9), + Name LowCardinality(String), + Attributes Map(LowCardinality(String), String) + ) CODEC(ZSTD(1)), + Links Nested ( + TraceId String, + SpanId String, + TraceState String, + Attributes Map(LowCardinality(String), String) + ) CODEC(ZSTD(1)), + INDEX idx_trace_id TraceId TYPE bloom_filter(0.001) GRANULARITY 1, + INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_span_attr_key mapKeys(SpanAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_span_attr_value mapValues(SpanAttributes) TYPE bloom_filter(0.01) GRANULARITY 1 +) ENGINE = MergeTree() +PARTITION BY toDate(Timestamp) +ORDER BY (ServiceName, SpanName, toUnixTimestamp(Timestamp), TraceId) +TTL toDateTime(Timestamp) + toIntervalDay(7) +SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1; + +CREATE TABLE IF NOT EXISTS otel.otel_metrics ( + ResourceAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ResourceSchemaUrl String CODEC(ZSTD(1)), + ScopeName String CODEC(ZSTD(1)), + ScopeVersion String CODEC(ZSTD(1)), + ScopeAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ScopeDroppedAttrCount UInt32 CODEC(ZSTD(1)), + ScopeSchemaUrl String CODEC(ZSTD(1)), + MetricName String CODEC(ZSTD(1)), + MetricDescription String CODEC(ZSTD(1)), + MetricUnit String CODEC(ZSTD(1)), + Attributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + StartTimeUnix DateTime64(9) CODEC(Delta, ZSTD(1)), + TimeUnix DateTime64(9) CODEC(Delta, ZSTD(1)), + Value Float64 CODEC(ZSTD(1)), + Flags UInt32 CODEC(ZSTD(1)), + Exemplars Nested ( + FilteredAttributes Map(LowCardinality(String), String), + TimeUnix DateTime64(9), + Value Float64, + SpanId String, + TraceId String + ) CODEC(ZSTD(1)), + AggTemp Int32 CODEC(ZSTD(1)), + IsMonotonic Bool CODEC(ZSTD(1)), + INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_key mapKeys(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_value mapValues(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_attr_key mapKeys(Attributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_attr_value mapValues(Attributes) TYPE bloom_filter(0.01) GRANULARITY 1 +) ENGINE = MergeTree() +PARTITION BY toDate(TimeUnix) +ORDER BY (MetricName, Attributes, toUnixTimestamp(TimeUnix)) +TTL toDateTime(TimeUnix) + toIntervalDay(30) +SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1; diff --git a/docker/dev-multidc-multinode/core/clickhouse/users.xml b/docker/dev-multidc-multinode/core/clickhouse/users.xml new file mode 100644 index 0000000000..743cada261 --- /dev/null +++ b/docker/dev-multidc-multinode/core/clickhouse/users.xml @@ -0,0 +1,35 @@ + + + + + default + + ::/0 + + default + default + 1 + + + + + + 10000000000 + 0 + random + + + + + + + 3600 + 0 + 0 + 0 + 0 + 0 + + + + diff --git a/docker/dev-multidc-multinode/core/grafana/dashboards/api.json b/docker/dev-multidc-multinode/core/grafana/dashboards/api.json new file mode 100644 index 0000000000..34004bf134 --- /dev/null +++ b/docker/dev-multidc-multinode/core/grafana/dashboards/api.json @@ -0,0 +1,1172 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 7, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 24, + "panels": [], + "title": "API", + "type": "row" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 26, + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_api_request_duration'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Request Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 27, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_api_request_pending'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Requests Pending", + "transformations": [ + { + "id": "groupingToMatrix", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 10 + }, + "id": 32, + "interval": "15s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n sum(Sum) / sum(Count) as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nHAVING sum(Count) > 0\nORDER BY time", + "refId": "A" + } + ], + "title": "Duration (avg)", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 10 + }, + "id": 33, + "interval": "15s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label, bounds, idx\nORDER BY time", + "refId": "A" + } + ], + "title": "Duration (p95)", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "bounds" + } + }, + { + "id": "convertFieldType", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 16, + "y": 10 + }, + "id": 34, + "interval": "15s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n Attributes['method'] as method,\n Attributes['path'] as path,\n histogramQuantile(arrayZip(ExplicitBounds, BucketCounts), 0.99) as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND Attributes['watch'] = '0'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, method, path\nORDER BY time", + "refId": "A" + } + ], + "title": "Duration (p99)", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 19 + }, + "id": 25, + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n sum(Value) / $__interval_ms * 1000 as value\n -- (\n -- SELECT\n -- sum(Value) / $__interval_ms * 1000 as value\n -- FROM otel.otel_metrics_sum\n -- WHERE MetricName = 'rivet_api_request_total'\n -- AND $__conditionalAll(Attributes['path'], $path)\n -- AND $__conditionalAll(Attributes['method'], $method)\n -- AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n -- AND $__timeFilter(TimeUnix)\n -- ) as prev_value\n -- lagInFrame(value, 1, value) OVER (ORDER BY time) as previous_value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_api_request_total'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Request Rate", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 19 + }, + "id": 28, + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Name", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}: {{status}} ({{error_code}})", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path'], ': ',\n Attributes['status'], ' (',\n Attributes['error_code'], ')'\n ) as label,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_api_request_errors'\n AND Attributes['status'] LIKE '4%'\n AND Attributes['error_code'] NOT IN ('API_CANCELLED', 'CAPTCHA_CAPTCHA_REQUIRED')\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Error Rate (4xx)", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\label" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 16, + "y": 19 + }, + "id": 31, + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}: {{status}} ({{error_code}})", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path'], ': ',\n Attributes['error_code'], ' (',\n Attributes['status'], ')'\n ) as label,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_api_request_errors'\n AND Attributes['status'] LIKE '5%'\n AND Attributes['error_code']-- NOT IN ('API_CANCELLED', 'CAPTCHA_CAPTCHA_REQUIRED')\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Error Rate (5xx)", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "log": 2, + "type": "log" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "percent" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 28 + }, + "id": 35, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{method}} {{path}}: {{status}} {{error_code}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['method'] as method,\n Attributes['path'] as path,\n Attributes['status'] as status,\n Attributes['error_code'] as error_code,\n sum(Count) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND (Attributes['status'] = '200' OR Attributes['status'] LIKE '5%')\n AND Attributes['error_code']-- NOT IN ('API_CANCELLED', 'CAPTCHA_CAPTCHA_REQUIRED')\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, method, path, status, error_code\nORDER BY time", + "refId": "A" + } + ], + "title": "200 vs 5xx (4xx excluded)", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "30s", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request_errors' ORDER BY datacenter_id", + "includeAll": true, + "label": "Datacenter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request_errors' ORDER BY datacenter_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['path'] as path FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) ORDER BY path", + "includeAll": true, + "label": "Path", + "multi": true, + "name": "path", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['path'] as path FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) ORDER BY path", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['method'] as method FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) AND $__conditionalAll(Attributes['path'], $path) ORDER BY method", + "includeAll": true, + "label": "Method", + "multi": true, + "name": "method", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['method'] as method FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) AND $__conditionalAll(Attributes['path'], $path) ORDER BY method", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-24h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "API", + "uid": "feg8y72gpm2o0c", + "version": 1, + "weekStart": "" +} diff --git a/docker/dev-multidc-multinode/core/grafana/dashboards/cache.json b/docker/dev-multidc-multinode/core/grafana/dashboards/cache.json new file mode 100644 index 0000000000..5d762023ea --- /dev/null +++ b/docker/dev-multidc-multinode/core/grafana/dashboards/cache.json @@ -0,0 +1,1176 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 4, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 10, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n CASE\n WHEN ResourceAttributes['datacenter_id'] != '' AND ResourceAttributes['server_id'] != '' THEN concat(ResourceAttributes['datacenter_id'], ' - ', ResourceAttributes['server_id'])\n ELSE 'Route Cache Size'\n END as label,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_route_cache_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Route Cache Size", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\label" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 11, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_rate_limiter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Rate Limiters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 12, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_in_flight_counter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "In-Flight Counters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 8 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_tcp_connection_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active TCP Connections", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 8 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_tcp_connection'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "TCP Connection Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 8 + }, + "id": 1, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_tcp_connection_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "TCP Connection Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 16 + }, + "id": 7, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_proxy_request_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Proxy Requests", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 16 + }, + "id": 8, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_proxy_request'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Proxy Request Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 16 + }, + "id": 9, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_proxy_request_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Proxy Request Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 24 + }, + "id": 6, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_resolve_route_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Resolve Route Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "description": "", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "description": "", + "includeAll": true, + "label": "Dataceter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "description": "", + "includeAll": true, + "label": "Server ID", + "multi": true, + "name": "server_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Rivet Guard", + "uid": "cen785ige8fswd", + "version": 1, + "weekStart": "" +} diff --git a/docker/dev-multidc-multinode/core/grafana/dashboards/futures.json b/docker/dev-multidc-multinode/core/grafana/dashboards/futures.json new file mode 100644 index 0000000000..0c992c4bcb --- /dev/null +++ b/docker/dev-multidc-multinode/core/grafana/dashboards/futures.json @@ -0,0 +1,208 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_instrumented_future_duration'\n AND $__conditionalAll(Attributes['name'], $name)\n AND $__conditionalAll(Attributes['location'], $location)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Instrumented Future Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "30s", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['name'] as name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY name", + "includeAll": true, + "label": "Name", + "multi": true, + "name": "name", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['name'] as name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY name", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['location'] as location FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY location", + "includeAll": true, + "label": "Location", + "multi": true, + "name": "location", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['location'] as location FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY location", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Futures", + "version": 0, + "weekStart": "" +} \ No newline at end of file diff --git a/docker/dev-multidc-multinode/core/grafana/dashboards/gasoline.json b/docker/dev-multidc-multinode/core/grafana/dashboards/gasoline.json new file mode 100644 index 0000000000..bac8c7b6da --- /dev/null +++ b/docker/dev-multidc-multinode/core/grafana/dashboards/gasoline.json @@ -0,0 +1,2583 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": 3, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{workflow_name}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_active'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Running Workflows", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 3, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{workflow_name}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_sleeping'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Sleeping Workflows", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 1, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{workflow_name}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_dead'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Dead Workflows", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 6, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "({{workflow_name}}) {{error_code}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n Attributes['error_code'] as error_code,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_dead'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name, error_code\nORDER BY time", + "refId": "A" + } + ], + "title": "Dead Workflow Errors", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "__auto", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n count(*) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_worker_last_ping'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Workers", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "datacenter_id", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\datacenter_id" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 4, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{signal_name}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['signal_name'] as signal_name,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_signal_pending'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, signal_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Pending Signals", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "signal_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\signal_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 10, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size", + "value": "" + }, + "yBuckets": { + "mode": "size", + "scale": { + "log": 2, + "type": "log" + }, + "value": "" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "hide": false, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_signal_recv_lag'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Signal Receive Lag", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 24 + }, + "id": 11, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_signal_pull_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY\n Time, le\nORDER BY\n Time, le", + "refId": "A" + } + ], + "title": "Pull Signals Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 32 + }, + "id": 13, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "instant": false, + "legendFormat": "{{worker_instance_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['worker_instance_id'] as worker_instance_id,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_last_pull_workflows_duration'\n AND ResourceAttributes['cluster_id'] LIKE '${cluster_id:regex}'\n AND ResourceAttributes['datacenter_id'] LIKE '${datacenter_id:regex}'\n AND $__timeFilter(TimeUnix)\nGROUP BY time, worker_instance_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Last Pull Workflows Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "worker_instance_id", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\worker_instance_id" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 32 + }, + "id": 14, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "instant": false, + "legendFormat": "{{worker_instance_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['worker_instance_id'] as worker_instance_id,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_last_pull_workflows_history_duration'\n AND ResourceAttributes['cluster_id'] LIKE '${cluster_id:regex}'\n AND ResourceAttributes['datacenter_id'] LIKE '${datacenter_id:regex}'\n AND $__timeFilter(TimeUnix)\nGROUP BY time, worker_instance_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Last Pull Workflows History Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "worker_instance_id", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\worker_instance_id" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 40 + }, + "id": 23, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_pull_workflows_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Pull Workflows Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 40 + }, + "id": 24, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_pull_workflows_history_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Pull Workflows History Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 48 + }, + "id": 16, + "panels": [], + "title": "Steps", + "type": "row" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 49 + }, + "id": 12, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_activity_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Activity Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 49 + }, + "id": 9, + "interval": "15s", + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{activity_name}}: {{error_code}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['activity_name'] as activity_name,\n Attributes['error_code'] as error_code,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_gasoline_activity_errors'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, activity_name, error_code\nORDER BY time", + "refId": "A" + } + ], + "title": "Activity Error Rate", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "activity_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\activity_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 58 + }, + "id": 21, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_loop_iteration_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Loop Upsert Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ev/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 58 + }, + "id": 25, + "interval": "15s", + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "legendFormat": "{{workflow_name}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n sum(Count) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_gasoline_loop_iteration_duration'\n AND Attributes['workflow_name'] LIKE '${workflow_name:regex}'\n AND ResourceAttributes['cluster_id'] LIKE '${cluster_id:regex}'\n AND ResourceAttributes['datacenter_id'] LIKE '${datacenter_id:regex}'\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Loop Events Per Second", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 67 + }, + "id": 17, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_message_send_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Message Send Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 67 + }, + "id": 20, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_signal_send_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Signal Send Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 76 + }, + "id": 22, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_find_workflows_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Find Workflows Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 76 + }, + "id": 19, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_workflow_dispatch_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Sub Workflow Dispatch Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "5s", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY cluster_id", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY cluster_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY datacenter_id", + "includeAll": true, + "label": "Datacenter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY datacenter_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['workflow_name'] as workflow_name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_gasoline_signal_recv_lag' ORDER BY workflow_name", + "includeAll": true, + "label": "Workflow Name", + "multi": true, + "name": "workflow_name", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['workflow_name'] as workflow_name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_gasoline_signal_recv_lag' ORDER BY workflow_name", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Gasoline", + "uid": "636d22f9-d18f-4086-8b45-7c50886a105c", + "version": 1, + "weekStart": "" +} diff --git a/docker/dev-multidc-multinode/core/grafana/dashboards/guard.json b/docker/dev-multidc-multinode/core/grafana/dashboards/guard.json new file mode 100644 index 0000000000..fb657d441b --- /dev/null +++ b/docker/dev-multidc-multinode/core/grafana/dashboards/guard.json @@ -0,0 +1,1150 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 115, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 10, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_route_cache_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Route Cache Size", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 11, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_rate_limiter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Rate Limiters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 12, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_in_flight_counter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "In-Flight Counters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 8 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_tcp_connection_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active TCP Connections", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 8 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_tcp_connection'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "TCP Connection Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 8 + }, + "id": 1, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_tcp_connection_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "TCP Connection Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 16 + }, + "id": 7, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_proxy_request_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Proxy Requests", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 16 + }, + "id": 8, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_proxy_request'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Proxy Request Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 16 + }, + "id": 9, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_proxy_request_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Proxy Request Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 24 + }, + "id": 6, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_resolve_route_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Resolve Route Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "description": "", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "description": "", + "includeAll": true, + "label": "Dataceter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "description": "", + "includeAll": true, + "label": "Server ID", + "multi": true, + "name": "server_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Rivet Guard", + "uid": "cen785ige8fswd", + "version": 1, + "weekStart": "" +} diff --git a/docker/dev-multidc-multinode/core/grafana/dashboards/tokio.json b/docker/dev-multidc-multinode/core/grafana/dashboards/tokio.json new file mode 100644 index 0000000000..efa5e4b49f --- /dev/null +++ b/docker/dev-multidc-multinode/core/grafana/dashboards/tokio.json @@ -0,0 +1,1009 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": 81, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 24, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_global_queue_depth'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Global Queue Depth", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 27, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_worker_local_queue_depth'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Worker Queue Depth", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 11, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_tokio_task_poll_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Task Poll Times", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 26, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_worker_overflow_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Worker Overflow Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 23, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_future_schedule_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Future Schedule Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 25, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_thread_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Thread Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "tasks/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 28, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_tokio_task'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Task Spawn Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 24 + }, + "id": 29, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_active_task_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Tasks", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "5s", + "schemaVersion": 40, + "templating": { + "list": [ + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY cluster_id", + "description": "", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY cluster_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY datacenter_id", + "description": "", + "includeAll": true, + "label": "Dataceter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY datacenter_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY server_id", + "description": "", + "includeAll": true, + "label": "Server ID", + "multi": true, + "name": "server_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY server_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['pool_type'] as pool_type FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY pool_type", + "includeAll": true, + "label": "Pool", + "multi": true, + "name": "pool_type", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['pool_type'] as pool_type FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY pool_type", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Tokio", + "uid": "636d22f9-d18f-4086-8b45-7c50886a105d", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/docker/dev-multidc-multinode/core/grafana/dashboards/traces.json b/docker/dev-multidc-multinode/core/grafana/dashboards/traces.json new file mode 100644 index 0000000000..64f6b552c9 --- /dev/null +++ b/docker/dev-multidc-multinode/core/grafana/dashboards/traces.json @@ -0,0 +1,979 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 21, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 9, + "panels": [], + "title": "Traces", + "type": "row" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "bars", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 0, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 1 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-traces" + }, + "editorType": "sql", + "format": 0, + "meta": { + "builderOptions": { + "aggregates": [ + { + "aggregateType": "count", + "column": "" + } + ], + "columns": [ + { + "hint": "time", + "name": "Timestamp", + "type": "DateTime64(9)" + } + ], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "hint": "time", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "ServiceName" + ], + "limit": 10000, + "mode": "trend", + "orderBy": [], + "queryType": "timeseries", + "table": "otel_traces" + } + }, + "pluginVersion": "4.0.6", + "queryType": "timeseries", + "rawSql": "SELECT\r\n $__timeInterval(Timestamp) as time,\r\n ServiceName,\r\n count() as ` `\r\nFROM otel.otel_traces\r\nWHERE\r\n ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )\r\n AND $__conditionalAll(ServiceName, $service_name)\r\n AND $__conditionalAll(SpanName, $span_name)\r\n AND (($ray_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['ray_id'], $ray_id))\r\n AND (($workflow_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['workflow_id'], $workflow_id))\r\nGROUP BY ServiceName, time\r\nORDER BY time ASC\r\nLIMIT 100000\r\n", + "refId": "A" + } + ], + "title": "Traces per Service", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Trace ID" + }, + "properties": [ + { + "id": "custom.width", + "value": 77 + }, + { + "id": "links", + "value": [ + { + "title": "__value.raw", + "url": "/d/8klBUGfVk/otel-traces?${__url_time_range}&${service_name:queryparam}&var-trace_id=${__value.raw}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Service Name" + }, + "properties": [ + { + "id": "custom.width", + "value": 130 + }, + { + "id": "links", + "value": [ + { + "title": "__value.raw", + "url": "/d/8klBUGfVk/otel-traces?${__url_time_range}&${trace_id:queryparam}&var-serviceName=${__value.raw}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Duration" + }, + "properties": [ + { + "id": "unit", + "value": "ms" + }, + { + "id": "custom.cellOptions", + "value": { + "mode": "lcd", + "type": "gauge", + "valueDisplayMode": "text" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "timestamp" + }, + "properties": [ + { + "id": "custom.width", + "value": 216 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Service Tags" + }, + "properties": [ + { + "id": "custom.inspect", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "timestamp" + }, + "properties": [ + { + "id": "custom.width", + "value": 248 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "timestamp" + }, + "properties": [ + { + "id": "custom.width", + "value": 234 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": " " + }, + "properties": [ + { + "id": "custom.width", + "value": 49 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Span Name" + }, + "properties": [ + { + "id": "custom.width", + "value": 140 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Ts" + }, + "properties": [ + { + "id": "custom.width", + "value": 168 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "URI/workflow_id/actor_id" + }, + "properties": [ + { + "id": "custom.width", + "value": 920 + } + ] + } + ] + }, + "gridPos": { + "h": 13, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 4, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Duration" + } + ] + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorType": "sql", + "format": 1, + "meta": { + "builderOptions": { + "columns": [], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "queryType": "table", + "table": "otel_traces" + } + }, + "pluginVersion": "4.9.0", + "queryType": "table", + "rawSql": "SELECT\r\n (argMin(StatusCode, Timestamp) = 'Error' ? '⚠️' : '') as ` `,\r\n min(Timestamp) as Ts,\r\n TraceId as `Trace ID`,\r\n argMin(ServiceName, Timestamp) as `Service Name`,\r\n argMin(SpanName, Timestamp) as `Span Name`,\r\n argMin(coalesce(NULLIF(SpanAttributes['uri'], ''), NULLIF(SpanAttributes['workflow_id'], ''), SpanAttributes['actor_id']), Timestamp) as `URI/workflow_id/actor_id`,\r\n divide(max(Duration), 1000000) as Duration\r\nFROM otel.otel_traces\r\nWHERE\r\n $__conditionalAll(ServiceName, $service_name)\r\n AND $__conditionalAll(SpanName, $span_name)\r\n AND (($ray_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['ray_id'], $ray_id))\r\n AND (($workflow_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['workflow_id'], $workflow_id))\r\n AND ServiceName != 'loadgenerator'\r\n AND ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )\r\nGROUP BY TraceId\r\nORDER BY Duration DESC\r\nLIMIT 100\r\n", + "refId": "A" + } + ], + "title": "Traces", + "type": "table" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, + "gridPos": { + "h": 17, + "w": 24, + "x": 0, + "y": 23 + }, + "id": 6, + "options": { + "spanFilters": { + "criticalPathOnly": false, + "matchesOnly": false, + "serviceNameOperator": "=", + "spanNameOperator": "=" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "builderOptions": { + "columns": [ + { + "hint": "trace_id", + "name": "TraceId" + }, + { + "hint": "trace_span_id", + "name": "SpanId" + }, + { + "hint": "trace_parent_span_id", + "name": "ParentSpanId" + }, + { + "hint": "trace_service_name", + "name": "ServiceName" + }, + { + "hint": "trace_operation_name", + "name": "SpanName" + }, + { + "hint": "time", + "name": "Timestamp" + }, + { + "hint": "trace_duration_time", + "name": "Duration" + }, + { + "hint": "trace_tags", + "name": "SpanAttributes" + }, + { + "hint": "trace_service_tags", + "name": "ResourceAttributes" + }, + { + "hint": "trace_status_code", + "name": "StatusCode" + } + ], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "hint": "time", + "key": "", + "operator": "WITH IN DASHBOARD TIME RANGE", + "type": "datetime" + }, + { + "condition": "AND", + "filterType": "custom", + "hint": "trace_duration_time", + "key": "", + "operator": ">", + "type": "UInt64", + "value": 0 + }, + { + "condition": "AND", + "filterType": "custom", + "hint": "trace_service_name", + "key": "", + "operator": "IS ANYTHING", + "type": "string", + "value": "" + } + ], + "limit": 1000, + "meta": { + "isTraceIdMode": true, + "otelEnabled": true, + "otelVersion": "latest", + "traceDurationUnit": "nanoseconds", + "traceId": "${trace_id}" + }, + "mode": "list", + "orderBy": [ + { + "default": true, + "dir": "DESC", + "hint": "time", + "name": "" + }, + { + "default": true, + "dir": "DESC", + "hint": "trace_duration_time", + "name": "" + } + ], + "queryType": "traces", + "table": "otel_traces" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-traces" + }, + "editorType": "builder", + "format": 3, + "meta": { + "builderOptions": { + "columns": [], + "database": "", + "limit": 100, + "mode": "list", + "queryType": "table", + "table": "" + } + }, + "pluginVersion": "4.0.6", + "queryType": "traces", + "rawSql": "WITH\n\t(SELECT min(Start) FROM otel.otel_traces_trace_id_ts WHERE $__conditionalAll(TraceId, $trace_id)) as trace_start,\n\t(SELECT max(End) + 1 FROM otel.otel_traces_trace_id_ts WHERE $__conditionalAll(TraceId, $trace_id)) as trace_end\nSELECT\n\tTraceId as traceID,\n\tSpanId as spanID,\n\tParentSpanId as parentSpanID,\n\tServiceName as serviceName,\n\tSpanName as operationName, Timestamp as startTime,\n\tmultiply(Duration, 0.000001) as duration,\n\tarrayMap(key -> map('key', key, 'value', SpanAttributes[key]), mapKeys(SpanAttributes)) as tags,\n\tarrayMap(key -> map('key', key, 'value', ResourceAttributes[key]), mapKeys(ResourceAttributes)) as serviceTags,\n\tarrayMap((name, timestamp, attributes) -> tuple(name, toString(multiply(toUnixTimestamp64Nano(timestamp), 0.000001)), arrayMap( key -> map('key', key, 'value', attributes[key]), mapKeys(attributes)))::Tuple(name String, timestamp String, fields Array(Map(String, String))), `Events.Name`, `Events.Timestamp`, `Events.Attributes`) AS logs,\n\tarrayMap((traceID, spanID, attributes) -> tuple(traceID, spanID, arrayMap(key -> map('key', key, 'value', attributes[key]), mapKeys(attributes)))::Tuple(traceID String, spanID String, tags Array(Map(String, String))), `Links.TraceId`, `Links.SpanId`, `Links.Attributes`) AS references\nFROM otel.otel_traces\nWHERE\n\t$__conditionalAll(traceID, $trace_id) AND startTime >= trace_start AND startTime <= trace_end AND ( Duration > 0 )\nORDER BY Timestamp DESC, Duration DESC\nLIMIT 1000", + "refId": "A" + } + ], + "title": "Trace Details", + "type": "traces" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "bars", + "fillOpacity": 24, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 8, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-traces" + }, + "editorType": "sql", + "format": 0, + "meta": { + "builderOptions": { + "aggregates": [ + { + "aggregateType": "count", + "column": "" + } + ], + "columns": [ + { + "hint": "time", + "name": "Timestamp", + "type": "DateTime64(9)" + } + ], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "hint": "time", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "ServiceName" + ], + "limit": 10000, + "mode": "trend", + "orderBy": [], + "queryType": "timeseries", + "table": "otel_traces" + } + }, + "pluginVersion": "4.0.6", + "queryType": "timeseries", + "rawSql": "SELECT\r\n $__timeInterval(Timestamp) as time,\r\n count(*) as ` `,\r\n ServiceName\r\nFROM otel.otel_traces\r\nWHERE\r\n $__conditionalAll(TraceId, $trace_id)\r\n AND ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )\r\n AND $__conditionalAll(ServiceName, $service_name)\r\n AND $__conditionalAll(SpanName, $span_name)\r\n AND (($ray_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['ray_id'], $ray_id)\r\n AND (($workflow_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['workflow_id'], $workflow_id))\r\n AND StatusCode IN ('Error', 'STATUS_CODE_ERROR')\r\n AND ServiceName != 'loadgenerator' GROUP BY ServiceName, time\r\nORDER BY time ASC\r\nLIMIT 100000", + "refId": "A" + } + ], + "title": "Error rates", + "type": "timeseries" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 49 + }, + "id": 10, + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 61 + }, + "id": 11, + "options": { + "dedupStrategy": "none", + "enableInfiniteScrolling": false, + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": true, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "builderOptions": { + "columns": [ + { + "hint": "time", + "name": "Timestamp", + "type": "DateTime64(9)" + }, + { + "hint": "log_level", + "name": "SeverityText", + "type": "LowCardinality(String)" + }, + { + "hint": "log_message", + "name": "Body", + "type": "String" + } + ], + "database": "otel", + "filters": [], + "limit": 1000, + "meta": { + "logMessageLike": "", + "otelVersion": "latest" + }, + "mode": "list", + "orderBy": [], + "queryType": "logs", + "table": "otel_logs" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorType": "builder", + "format": 2, + "pluginVersion": "4.0.6", + "rawSql": "SELECT Timestamp as timestamp, Body as body, SeverityText as level FROM \"otel\".\"otel_logs\" LIMIT 1000", + "refId": "A" + } + ], + "title": "Trace Logs", + "type": "logs" + } + ], + "title": "Logs", + "type": "row" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "ClickHouse", + "value": "ClickHouse" + }, + "includeAll": false, + "label": "ClickHouse instance", + "name": "datasource", + "options": [], + "query": "grafana-clickhouse-datasource", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ServiceName FROM otel.otel_traces", + "includeAll": true, + "label": "Service Name", + "multi": true, + "name": "service_name", + "options": [], + "query": "SELECT DISTINCT ServiceName FROM otel.otel_traces", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT TraceId FROM otel.otel_traces WHERE ParentSpanId = '' LIMIT 100", + "includeAll": true, + "label": "Trace ID", + "name": "trace_id", + "options": [], + "query": "SELECT DISTINCT TraceId FROM otel.otel_traces WHERE ParentSpanId = '' LIMIT 100", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT SpanName FROM otel.otel_traces WHERE $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "description": "", + "includeAll": true, + "label": "Span", + "multi": true, + "name": "span_name", + "options": [], + "query": "SELECT DISTINCT SpanName FROM otel.otel_traces WHERE $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "allValue": "'All'", + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT SpanAttributes['ray_id'] FROM otel.otel_traces WHERE SpanAttributes['ray_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "description": "", + "includeAll": true, + "label": "Ray ID", + "multi": true, + "name": "ray_id", + "options": [], + "query": "SELECT DISTINCT SpanAttributes['ray_id'] FROM otel.otel_traces WHERE SpanAttributes['ray_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "allValue": "'All'", + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT SpanAttributes['workflow_id'] FROM otel.otel_traces WHERE SpanAttributes['workflow_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "description": "", + "includeAll": true, + "label": "Workflow ID", + "multi": true, + "name": "workflow_id", + "options": [], + "query": "SELECT DISTINCT SpanAttributes['workflow_id'] FROM otel.otel_traces WHERE SpanAttributes['workflow_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "America/Los_Angeles", + "title": "Traces", + "uid": "8klBUGfVk", + "version": 2, + "weekStart": "" +} diff --git a/docker/dev-multidc-multinode/core/grafana/grafana.ini b/docker/dev-multidc-multinode/core/grafana/grafana.ini new file mode 100644 index 0000000000..1bd9bfe697 --- /dev/null +++ b/docker/dev-multidc-multinode/core/grafana/grafana.ini @@ -0,0 +1,14 @@ +[server] +http_port = 3000 +root_url = http://localhost:3100 + +[security] +admin_user = admin +admin_password = admin + +[auth.anonymous] +enabled = true +org_role = Viewer + +[dashboards] +default_home_dashboard_path = /var/lib/grafana/dashboards/api.json diff --git a/docker/dev-multidc-multinode/core/grafana/provisioning/dashboards/dashboards.yaml b/docker/dev-multidc-multinode/core/grafana/provisioning/dashboards/dashboards.yaml new file mode 100644 index 0000000000..7d91589dc7 --- /dev/null +++ b/docker/dev-multidc-multinode/core/grafana/provisioning/dashboards/dashboards.yaml @@ -0,0 +1,10 @@ +apiVersion: 1 +providers: + - name: rivet-dashboards + orgId: 1 + folder: '' + type: file + disableDeletion: false + updateIntervalSeconds: 10 + options: + path: /var/lib/grafana/dashboards diff --git a/docker/dev-multidc-multinode/core/grafana/provisioning/datasources/datasources.yaml b/docker/dev-multidc-multinode/core/grafana/provisioning/datasources/datasources.yaml new file mode 100644 index 0000000000..f66d3bf036 --- /dev/null +++ b/docker/dev-multidc-multinode/core/grafana/provisioning/datasources/datasources.yaml @@ -0,0 +1,30 @@ +apiVersion: 1 +datasources: + - name: ClickHouse + uid: clickhouse + type: grafana-clickhouse-datasource + access: proxy + secureJsonData: + password: default + jsonData: + version: 2.0.0 + host: clickhouse + port: 9300 + defaultDatabase: default + protocol: http + secure: false + username: default + validateSql: true + logs: + otelEnabled: true + otelVersion: 1.2.9 + defaultDatabase: otel + defaultTable: otel_logs + timeColumn: TimestampTime + messageColumn: Body + levelColumn: SeverityText + traces: + otelEnabled: true + otelVersion: 1.2.9 + defaultDatabase: otel + defaultTable: otel_traces diff --git a/docker/dev-multidc-multinode/datacenters/dc-a/otel-collector-client/config.yaml b/docker/dev-multidc-multinode/datacenters/dc-a/otel-collector-client/config.yaml new file mode 100644 index 0000000000..f3077ceb1c --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-a/otel-collector-client/config.yaml @@ -0,0 +1,39 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + http: + endpoint: 0.0.0.0:4318 +processors: + batch: + timeout: 5s + send_batch_size: 10000 +exporters: + otlp/server: + endpoint: otel-collector-server-dc-a:4317 + tls: + insecure: true +service: + pipelines: + logs: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server + traces: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server + metrics: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server diff --git a/docker/dev-multidc-multinode/datacenters/dc-a/otel-collector-server/config.yaml b/docker/dev-multidc-multinode/datacenters/dc-a/otel-collector-server/config.yaml new file mode 100644 index 0000000000..a74179019e --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-a/otel-collector-server/config.yaml @@ -0,0 +1,61 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 +processors: + batch: + timeout: 5s + send_batch_size: 10000 +exporters: + clickhouse: + endpoint: http://clickhouse:9300 + database: otel + username: default + password: ${env:CLICKHOUSE_PASSWORD} + async_insert: true + ttl: 72h + compress: lz4 + create_schema: true + logs_table_name: otel_logs + traces_table_name: otel_traces + timeout: 5s + metrics_tables: + gauge: + name: otel_metrics_gauge + sum: + name: otel_metrics_sum + summary: + name: otel_metrics_summary + histogram: + name: otel_metrics_histogram + exponential_histogram: + name: otel_metrics_exp_histogram + retry_on_failure: + enabled: true + initial_interval: 5s + max_interval: 30s + max_elapsed_time: 300s +service: + pipelines: + logs: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse + traces: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse + metrics: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse diff --git a/docker/dev-multidc-multinode/datacenters/dc-a/postgres/init-db.sh b/docker/dev-multidc-multinode/datacenters/dc-a/postgres/init-db.sh new file mode 100755 index 0000000000..6b57fcfef7 --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-a/postgres/init-db.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -e + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + CREATE DATABASE rivet_engine; +EOSQL diff --git a/docker/dev-multidc-multinode/datacenters/dc-a/rivet-engine/0/config.jsonc b/docker/dev-multidc-multinode/datacenters/dc-a/rivet-engine/0/config.jsonc new file mode 100644 index 0000000000..7b59fba448 --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-a/rivet-engine/0/config.jsonc @@ -0,0 +1,70 @@ +{ + "guard": { + "port": 6420 + }, + "api_public": { + "lan_host": "rivet-engine-dc-a-0", + "host": "0.0.0.0", + "port": 6421 + }, + "api_peer": { + "host": "0.0.0.0", + "port": 6422 + }, + "pegboard": { + "lan_host": "rivet-engine-dc-a-0", + "host": "0.0.0.0", + "port": 6423 + }, + "logs": {}, + "topology": { + "datacenter_label": 1, + "datacenters": [ + { + "name": "dc-a", + "datacenter_label": 1, + "is_leader": true, + "api_peer_url": "http://rivet-engine-dc-a-0:6422", + "guard_url": "http://rivet-engine-dc-a-0:6420" + }, + { + "name": "dc-b", + "datacenter_label": 2, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-b-0:6422", + "guard_url": "http://rivet-engine-dc-b-0:6420" + }, + { + "name": "dc-c", + "datacenter_label": 3, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-c-0:6422", + "guard_url": "http://rivet-engine-dc-c-0:6420" + } + ] + }, + "postgres": { + "url": "postgresql://postgres:postgres@postgres-dc-a:5432/rivet_engine" + }, + "cache": { + "driver": "in_memory" + }, + "clickhouse": { + "http_url": "http://clickhouse:9300", + "native_url": "http://clickhouse:9301", + "username": "system", + "password": "default", + "provision_users": { + "vector": { + "username": "vector", + "password": "vector", + "role": "write" + } + }, + "secure": false + }, + "vector_http": { + "host": "vector-client-dc-a", + "port": 5022 + } +} \ No newline at end of file diff --git a/docker/dev-multidc-multinode/datacenters/dc-a/rivet-engine/1/config.jsonc b/docker/dev-multidc-multinode/datacenters/dc-a/rivet-engine/1/config.jsonc new file mode 100644 index 0000000000..7b59fba448 --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-a/rivet-engine/1/config.jsonc @@ -0,0 +1,70 @@ +{ + "guard": { + "port": 6420 + }, + "api_public": { + "lan_host": "rivet-engine-dc-a-0", + "host": "0.0.0.0", + "port": 6421 + }, + "api_peer": { + "host": "0.0.0.0", + "port": 6422 + }, + "pegboard": { + "lan_host": "rivet-engine-dc-a-0", + "host": "0.0.0.0", + "port": 6423 + }, + "logs": {}, + "topology": { + "datacenter_label": 1, + "datacenters": [ + { + "name": "dc-a", + "datacenter_label": 1, + "is_leader": true, + "api_peer_url": "http://rivet-engine-dc-a-0:6422", + "guard_url": "http://rivet-engine-dc-a-0:6420" + }, + { + "name": "dc-b", + "datacenter_label": 2, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-b-0:6422", + "guard_url": "http://rivet-engine-dc-b-0:6420" + }, + { + "name": "dc-c", + "datacenter_label": 3, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-c-0:6422", + "guard_url": "http://rivet-engine-dc-c-0:6420" + } + ] + }, + "postgres": { + "url": "postgresql://postgres:postgres@postgres-dc-a:5432/rivet_engine" + }, + "cache": { + "driver": "in_memory" + }, + "clickhouse": { + "http_url": "http://clickhouse:9300", + "native_url": "http://clickhouse:9301", + "username": "system", + "password": "default", + "provision_users": { + "vector": { + "username": "vector", + "password": "vector", + "role": "write" + } + }, + "secure": false + }, + "vector_http": { + "host": "vector-client-dc-a", + "port": 5022 + } +} \ No newline at end of file diff --git a/docker/dev-multidc-multinode/datacenters/dc-a/rivet-engine/2/config.jsonc b/docker/dev-multidc-multinode/datacenters/dc-a/rivet-engine/2/config.jsonc new file mode 100644 index 0000000000..7b59fba448 --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-a/rivet-engine/2/config.jsonc @@ -0,0 +1,70 @@ +{ + "guard": { + "port": 6420 + }, + "api_public": { + "lan_host": "rivet-engine-dc-a-0", + "host": "0.0.0.0", + "port": 6421 + }, + "api_peer": { + "host": "0.0.0.0", + "port": 6422 + }, + "pegboard": { + "lan_host": "rivet-engine-dc-a-0", + "host": "0.0.0.0", + "port": 6423 + }, + "logs": {}, + "topology": { + "datacenter_label": 1, + "datacenters": [ + { + "name": "dc-a", + "datacenter_label": 1, + "is_leader": true, + "api_peer_url": "http://rivet-engine-dc-a-0:6422", + "guard_url": "http://rivet-engine-dc-a-0:6420" + }, + { + "name": "dc-b", + "datacenter_label": 2, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-b-0:6422", + "guard_url": "http://rivet-engine-dc-b-0:6420" + }, + { + "name": "dc-c", + "datacenter_label": 3, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-c-0:6422", + "guard_url": "http://rivet-engine-dc-c-0:6420" + } + ] + }, + "postgres": { + "url": "postgresql://postgres:postgres@postgres-dc-a:5432/rivet_engine" + }, + "cache": { + "driver": "in_memory" + }, + "clickhouse": { + "http_url": "http://clickhouse:9300", + "native_url": "http://clickhouse:9301", + "username": "system", + "password": "default", + "provision_users": { + "vector": { + "username": "vector", + "password": "vector", + "role": "write" + } + }, + "secure": false + }, + "vector_http": { + "host": "vector-client-dc-a", + "port": 5022 + } +} \ No newline at end of file diff --git a/docker/dev-multidc-multinode/datacenters/dc-a/vector-client/vector.yaml b/docker/dev-multidc-multinode/datacenters/dc-a/vector-client/vector.yaml new file mode 100644 index 0000000000..f71830ca66 --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-a/vector-client/vector.yaml @@ -0,0 +1,31 @@ +# Vector Client Configuration for Datacenter: dc-a +# This Vector instance runs on each server to collect local logs and forward them +# to the central Vector server aggregator. + +api: + enabled: true + address: 0.0.0.0:8686 +sources: + http_events: + type: http_server + address: 0.0.0.0:5022 + encoding: ndjson +transforms: {} +sinks: + vector_server: + type: vector + inputs: + - http_events + address: vector-server-dc-a:6000 + version: '2' + buffer: + type: disk + max_size: 2147483648 + when_full: block + console_debug: + type: console + inputs: + - http_events + encoding: + codec: json + \ No newline at end of file diff --git a/docker/dev-multidc-multinode/datacenters/dc-a/vector-server/vector.yaml b/docker/dev-multidc-multinode/datacenters/dc-a/vector-server/vector.yaml new file mode 100644 index 0000000000..5dfdbff2f5 --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-a/vector-server/vector.yaml @@ -0,0 +1,61 @@ +# Vector Server (Aggregator) Configuration +# This Vector instance acts as an aggregator that collects logs and metrics from all Vector clients +# across different datacenters and forwards them to ClickHouse and other sinks. + +api: + enabled: true + address: 0.0.0.0:8686 +sources: + vector: + type: vector + address: 0.0.0.0:6000 + version: '2' + tcp_json: + type: socket + mode: tcp + address: 0.0.0.0:6100 + decoding: + codec: json + http_json: + type: http_server + address: 0.0.0.0:6200 + encoding: json + vector_metrics: + type: internal_metrics + vector_logs: + type: internal_logs +transforms: + clickhouse_dynamic_events_filter: + type: filter + inputs: + - vector + condition: + type: vrl + source: .source == "clickhouse" + clickhouse_dynamic_events_transform: + type: remap + inputs: + - clickhouse_dynamic_events_filter + source: "# Extract and store metadata\n__database = .database\n__table = .table\n__columns = .columns\n\n# Create a new object with just the columns data\n. = {\n\t\"__database\": __database,\n\t\"__table\": __table,\n\t# By default insert namespace column since most tables include this\n\t\"namespace\": \"rivet\"\n}\n\t\n# Merge in the column data that should be inserted\n. = merge!(., __columns)\n" +sinks: + clickhouse_dynamic_events: + type: clickhouse + inputs: + - clickhouse_dynamic_events_transform + endpoint: http://clickhouse:9300 + database: '{{ __database }}' + table: '{{ __table }}' + compression: gzip + auth: + strategy: basic + user: system + password: default + batch: + max_events: 1000 + timeout_secs: 10 + console_vector_logs: + type: console + inputs: + - vector_logs + encoding: + codec: json diff --git a/docker/dev-multidc-multinode/datacenters/dc-b/otel-collector-client/config.yaml b/docker/dev-multidc-multinode/datacenters/dc-b/otel-collector-client/config.yaml new file mode 100644 index 0000000000..a187be889a --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-b/otel-collector-client/config.yaml @@ -0,0 +1,39 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + http: + endpoint: 0.0.0.0:4318 +processors: + batch: + timeout: 5s + send_batch_size: 10000 +exporters: + otlp/server: + endpoint: otel-collector-server-dc-b:4317 + tls: + insecure: true +service: + pipelines: + logs: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server + traces: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server + metrics: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server diff --git a/docker/dev-multidc-multinode/datacenters/dc-b/otel-collector-server/config.yaml b/docker/dev-multidc-multinode/datacenters/dc-b/otel-collector-server/config.yaml new file mode 100644 index 0000000000..a74179019e --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-b/otel-collector-server/config.yaml @@ -0,0 +1,61 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 +processors: + batch: + timeout: 5s + send_batch_size: 10000 +exporters: + clickhouse: + endpoint: http://clickhouse:9300 + database: otel + username: default + password: ${env:CLICKHOUSE_PASSWORD} + async_insert: true + ttl: 72h + compress: lz4 + create_schema: true + logs_table_name: otel_logs + traces_table_name: otel_traces + timeout: 5s + metrics_tables: + gauge: + name: otel_metrics_gauge + sum: + name: otel_metrics_sum + summary: + name: otel_metrics_summary + histogram: + name: otel_metrics_histogram + exponential_histogram: + name: otel_metrics_exp_histogram + retry_on_failure: + enabled: true + initial_interval: 5s + max_interval: 30s + max_elapsed_time: 300s +service: + pipelines: + logs: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse + traces: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse + metrics: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse diff --git a/docker/dev-multidc-multinode/datacenters/dc-b/postgres/init-db.sh b/docker/dev-multidc-multinode/datacenters/dc-b/postgres/init-db.sh new file mode 100755 index 0000000000..6b57fcfef7 --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-b/postgres/init-db.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -e + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + CREATE DATABASE rivet_engine; +EOSQL diff --git a/docker/dev-multidc-multinode/datacenters/dc-b/rivet-engine/0/config.jsonc b/docker/dev-multidc-multinode/datacenters/dc-b/rivet-engine/0/config.jsonc new file mode 100644 index 0000000000..aab7c3cd62 --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-b/rivet-engine/0/config.jsonc @@ -0,0 +1,70 @@ +{ + "guard": { + "port": 6420 + }, + "api_public": { + "lan_host": "rivet-engine-dc-b-0", + "host": "0.0.0.0", + "port": 6421 + }, + "api_peer": { + "host": "0.0.0.0", + "port": 6422 + }, + "pegboard": { + "lan_host": "rivet-engine-dc-b-0", + "host": "0.0.0.0", + "port": 6423 + }, + "logs": {}, + "topology": { + "datacenter_label": 2, + "datacenters": [ + { + "name": "dc-a", + "datacenter_label": 1, + "is_leader": true, + "api_peer_url": "http://rivet-engine-dc-a-0:6422", + "guard_url": "http://rivet-engine-dc-a-0:6420" + }, + { + "name": "dc-b", + "datacenter_label": 2, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-b-0:6422", + "guard_url": "http://rivet-engine-dc-b-0:6420" + }, + { + "name": "dc-c", + "datacenter_label": 3, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-c-0:6422", + "guard_url": "http://rivet-engine-dc-c-0:6420" + } + ] + }, + "postgres": { + "url": "postgresql://postgres:postgres@postgres-dc-b:5432/rivet_engine" + }, + "cache": { + "driver": "in_memory" + }, + "clickhouse": { + "http_url": "http://clickhouse:9300", + "native_url": "http://clickhouse:9301", + "username": "system", + "password": "default", + "provision_users": { + "vector": { + "username": "vector", + "password": "vector", + "role": "write" + } + }, + "secure": false + }, + "vector_http": { + "host": "vector-client-dc-b", + "port": 5022 + } +} \ No newline at end of file diff --git a/docker/dev-multidc-multinode/datacenters/dc-b/rivet-engine/1/config.jsonc b/docker/dev-multidc-multinode/datacenters/dc-b/rivet-engine/1/config.jsonc new file mode 100644 index 0000000000..aab7c3cd62 --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-b/rivet-engine/1/config.jsonc @@ -0,0 +1,70 @@ +{ + "guard": { + "port": 6420 + }, + "api_public": { + "lan_host": "rivet-engine-dc-b-0", + "host": "0.0.0.0", + "port": 6421 + }, + "api_peer": { + "host": "0.0.0.0", + "port": 6422 + }, + "pegboard": { + "lan_host": "rivet-engine-dc-b-0", + "host": "0.0.0.0", + "port": 6423 + }, + "logs": {}, + "topology": { + "datacenter_label": 2, + "datacenters": [ + { + "name": "dc-a", + "datacenter_label": 1, + "is_leader": true, + "api_peer_url": "http://rivet-engine-dc-a-0:6422", + "guard_url": "http://rivet-engine-dc-a-0:6420" + }, + { + "name": "dc-b", + "datacenter_label": 2, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-b-0:6422", + "guard_url": "http://rivet-engine-dc-b-0:6420" + }, + { + "name": "dc-c", + "datacenter_label": 3, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-c-0:6422", + "guard_url": "http://rivet-engine-dc-c-0:6420" + } + ] + }, + "postgres": { + "url": "postgresql://postgres:postgres@postgres-dc-b:5432/rivet_engine" + }, + "cache": { + "driver": "in_memory" + }, + "clickhouse": { + "http_url": "http://clickhouse:9300", + "native_url": "http://clickhouse:9301", + "username": "system", + "password": "default", + "provision_users": { + "vector": { + "username": "vector", + "password": "vector", + "role": "write" + } + }, + "secure": false + }, + "vector_http": { + "host": "vector-client-dc-b", + "port": 5022 + } +} \ No newline at end of file diff --git a/docker/dev-multidc-multinode/datacenters/dc-b/rivet-engine/2/config.jsonc b/docker/dev-multidc-multinode/datacenters/dc-b/rivet-engine/2/config.jsonc new file mode 100644 index 0000000000..aab7c3cd62 --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-b/rivet-engine/2/config.jsonc @@ -0,0 +1,70 @@ +{ + "guard": { + "port": 6420 + }, + "api_public": { + "lan_host": "rivet-engine-dc-b-0", + "host": "0.0.0.0", + "port": 6421 + }, + "api_peer": { + "host": "0.0.0.0", + "port": 6422 + }, + "pegboard": { + "lan_host": "rivet-engine-dc-b-0", + "host": "0.0.0.0", + "port": 6423 + }, + "logs": {}, + "topology": { + "datacenter_label": 2, + "datacenters": [ + { + "name": "dc-a", + "datacenter_label": 1, + "is_leader": true, + "api_peer_url": "http://rivet-engine-dc-a-0:6422", + "guard_url": "http://rivet-engine-dc-a-0:6420" + }, + { + "name": "dc-b", + "datacenter_label": 2, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-b-0:6422", + "guard_url": "http://rivet-engine-dc-b-0:6420" + }, + { + "name": "dc-c", + "datacenter_label": 3, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-c-0:6422", + "guard_url": "http://rivet-engine-dc-c-0:6420" + } + ] + }, + "postgres": { + "url": "postgresql://postgres:postgres@postgres-dc-b:5432/rivet_engine" + }, + "cache": { + "driver": "in_memory" + }, + "clickhouse": { + "http_url": "http://clickhouse:9300", + "native_url": "http://clickhouse:9301", + "username": "system", + "password": "default", + "provision_users": { + "vector": { + "username": "vector", + "password": "vector", + "role": "write" + } + }, + "secure": false + }, + "vector_http": { + "host": "vector-client-dc-b", + "port": 5022 + } +} \ No newline at end of file diff --git a/docker/dev-multidc-multinode/datacenters/dc-b/vector-client/vector.yaml b/docker/dev-multidc-multinode/datacenters/dc-b/vector-client/vector.yaml new file mode 100644 index 0000000000..d1f0cda93c --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-b/vector-client/vector.yaml @@ -0,0 +1,31 @@ +# Vector Client Configuration for Datacenter: dc-b +# This Vector instance runs on each server to collect local logs and forward them +# to the central Vector server aggregator. + +api: + enabled: true + address: 0.0.0.0:8686 +sources: + http_events: + type: http_server + address: 0.0.0.0:5022 + encoding: ndjson +transforms: {} +sinks: + vector_server: + type: vector + inputs: + - http_events + address: vector-server-dc-b:6000 + version: '2' + buffer: + type: disk + max_size: 2147483648 + when_full: block + console_debug: + type: console + inputs: + - http_events + encoding: + codec: json + \ No newline at end of file diff --git a/docker/dev-multidc-multinode/datacenters/dc-b/vector-server/vector.yaml b/docker/dev-multidc-multinode/datacenters/dc-b/vector-server/vector.yaml new file mode 100644 index 0000000000..5dfdbff2f5 --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-b/vector-server/vector.yaml @@ -0,0 +1,61 @@ +# Vector Server (Aggregator) Configuration +# This Vector instance acts as an aggregator that collects logs and metrics from all Vector clients +# across different datacenters and forwards them to ClickHouse and other sinks. + +api: + enabled: true + address: 0.0.0.0:8686 +sources: + vector: + type: vector + address: 0.0.0.0:6000 + version: '2' + tcp_json: + type: socket + mode: tcp + address: 0.0.0.0:6100 + decoding: + codec: json + http_json: + type: http_server + address: 0.0.0.0:6200 + encoding: json + vector_metrics: + type: internal_metrics + vector_logs: + type: internal_logs +transforms: + clickhouse_dynamic_events_filter: + type: filter + inputs: + - vector + condition: + type: vrl + source: .source == "clickhouse" + clickhouse_dynamic_events_transform: + type: remap + inputs: + - clickhouse_dynamic_events_filter + source: "# Extract and store metadata\n__database = .database\n__table = .table\n__columns = .columns\n\n# Create a new object with just the columns data\n. = {\n\t\"__database\": __database,\n\t\"__table\": __table,\n\t# By default insert namespace column since most tables include this\n\t\"namespace\": \"rivet\"\n}\n\t\n# Merge in the column data that should be inserted\n. = merge!(., __columns)\n" +sinks: + clickhouse_dynamic_events: + type: clickhouse + inputs: + - clickhouse_dynamic_events_transform + endpoint: http://clickhouse:9300 + database: '{{ __database }}' + table: '{{ __table }}' + compression: gzip + auth: + strategy: basic + user: system + password: default + batch: + max_events: 1000 + timeout_secs: 10 + console_vector_logs: + type: console + inputs: + - vector_logs + encoding: + codec: json diff --git a/docker/dev-multidc-multinode/datacenters/dc-c/otel-collector-client/config.yaml b/docker/dev-multidc-multinode/datacenters/dc-c/otel-collector-client/config.yaml new file mode 100644 index 0000000000..ca6a47e900 --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-c/otel-collector-client/config.yaml @@ -0,0 +1,39 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + http: + endpoint: 0.0.0.0:4318 +processors: + batch: + timeout: 5s + send_batch_size: 10000 +exporters: + otlp/server: + endpoint: otel-collector-server-dc-c:4317 + tls: + insecure: true +service: + pipelines: + logs: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server + traces: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server + metrics: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server diff --git a/docker/dev-multidc-multinode/datacenters/dc-c/otel-collector-server/config.yaml b/docker/dev-multidc-multinode/datacenters/dc-c/otel-collector-server/config.yaml new file mode 100644 index 0000000000..a74179019e --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-c/otel-collector-server/config.yaml @@ -0,0 +1,61 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 +processors: + batch: + timeout: 5s + send_batch_size: 10000 +exporters: + clickhouse: + endpoint: http://clickhouse:9300 + database: otel + username: default + password: ${env:CLICKHOUSE_PASSWORD} + async_insert: true + ttl: 72h + compress: lz4 + create_schema: true + logs_table_name: otel_logs + traces_table_name: otel_traces + timeout: 5s + metrics_tables: + gauge: + name: otel_metrics_gauge + sum: + name: otel_metrics_sum + summary: + name: otel_metrics_summary + histogram: + name: otel_metrics_histogram + exponential_histogram: + name: otel_metrics_exp_histogram + retry_on_failure: + enabled: true + initial_interval: 5s + max_interval: 30s + max_elapsed_time: 300s +service: + pipelines: + logs: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse + traces: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse + metrics: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse diff --git a/docker/dev-multidc-multinode/datacenters/dc-c/postgres/init-db.sh b/docker/dev-multidc-multinode/datacenters/dc-c/postgres/init-db.sh new file mode 100755 index 0000000000..6b57fcfef7 --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-c/postgres/init-db.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -e + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + CREATE DATABASE rivet_engine; +EOSQL diff --git a/docker/dev-multidc-multinode/datacenters/dc-c/rivet-engine/0/config.jsonc b/docker/dev-multidc-multinode/datacenters/dc-c/rivet-engine/0/config.jsonc new file mode 100644 index 0000000000..2555b0bdec --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-c/rivet-engine/0/config.jsonc @@ -0,0 +1,70 @@ +{ + "guard": { + "port": 6420 + }, + "api_public": { + "lan_host": "rivet-engine-dc-c-0", + "host": "0.0.0.0", + "port": 6421 + }, + "api_peer": { + "host": "0.0.0.0", + "port": 6422 + }, + "pegboard": { + "lan_host": "rivet-engine-dc-c-0", + "host": "0.0.0.0", + "port": 6423 + }, + "logs": {}, + "topology": { + "datacenter_label": 3, + "datacenters": [ + { + "name": "dc-a", + "datacenter_label": 1, + "is_leader": true, + "api_peer_url": "http://rivet-engine-dc-a-0:6422", + "guard_url": "http://rivet-engine-dc-a-0:6420" + }, + { + "name": "dc-b", + "datacenter_label": 2, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-b-0:6422", + "guard_url": "http://rivet-engine-dc-b-0:6420" + }, + { + "name": "dc-c", + "datacenter_label": 3, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-c-0:6422", + "guard_url": "http://rivet-engine-dc-c-0:6420" + } + ] + }, + "postgres": { + "url": "postgresql://postgres:postgres@postgres-dc-c:5432/rivet_engine" + }, + "cache": { + "driver": "in_memory" + }, + "clickhouse": { + "http_url": "http://clickhouse:9300", + "native_url": "http://clickhouse:9301", + "username": "system", + "password": "default", + "provision_users": { + "vector": { + "username": "vector", + "password": "vector", + "role": "write" + } + }, + "secure": false + }, + "vector_http": { + "host": "vector-client-dc-c", + "port": 5022 + } +} \ No newline at end of file diff --git a/docker/dev-multidc-multinode/datacenters/dc-c/rivet-engine/1/config.jsonc b/docker/dev-multidc-multinode/datacenters/dc-c/rivet-engine/1/config.jsonc new file mode 100644 index 0000000000..2555b0bdec --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-c/rivet-engine/1/config.jsonc @@ -0,0 +1,70 @@ +{ + "guard": { + "port": 6420 + }, + "api_public": { + "lan_host": "rivet-engine-dc-c-0", + "host": "0.0.0.0", + "port": 6421 + }, + "api_peer": { + "host": "0.0.0.0", + "port": 6422 + }, + "pegboard": { + "lan_host": "rivet-engine-dc-c-0", + "host": "0.0.0.0", + "port": 6423 + }, + "logs": {}, + "topology": { + "datacenter_label": 3, + "datacenters": [ + { + "name": "dc-a", + "datacenter_label": 1, + "is_leader": true, + "api_peer_url": "http://rivet-engine-dc-a-0:6422", + "guard_url": "http://rivet-engine-dc-a-0:6420" + }, + { + "name": "dc-b", + "datacenter_label": 2, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-b-0:6422", + "guard_url": "http://rivet-engine-dc-b-0:6420" + }, + { + "name": "dc-c", + "datacenter_label": 3, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-c-0:6422", + "guard_url": "http://rivet-engine-dc-c-0:6420" + } + ] + }, + "postgres": { + "url": "postgresql://postgres:postgres@postgres-dc-c:5432/rivet_engine" + }, + "cache": { + "driver": "in_memory" + }, + "clickhouse": { + "http_url": "http://clickhouse:9300", + "native_url": "http://clickhouse:9301", + "username": "system", + "password": "default", + "provision_users": { + "vector": { + "username": "vector", + "password": "vector", + "role": "write" + } + }, + "secure": false + }, + "vector_http": { + "host": "vector-client-dc-c", + "port": 5022 + } +} \ No newline at end of file diff --git a/docker/dev-multidc-multinode/datacenters/dc-c/rivet-engine/2/config.jsonc b/docker/dev-multidc-multinode/datacenters/dc-c/rivet-engine/2/config.jsonc new file mode 100644 index 0000000000..2555b0bdec --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-c/rivet-engine/2/config.jsonc @@ -0,0 +1,70 @@ +{ + "guard": { + "port": 6420 + }, + "api_public": { + "lan_host": "rivet-engine-dc-c-0", + "host": "0.0.0.0", + "port": 6421 + }, + "api_peer": { + "host": "0.0.0.0", + "port": 6422 + }, + "pegboard": { + "lan_host": "rivet-engine-dc-c-0", + "host": "0.0.0.0", + "port": 6423 + }, + "logs": {}, + "topology": { + "datacenter_label": 3, + "datacenters": [ + { + "name": "dc-a", + "datacenter_label": 1, + "is_leader": true, + "api_peer_url": "http://rivet-engine-dc-a-0:6422", + "guard_url": "http://rivet-engine-dc-a-0:6420" + }, + { + "name": "dc-b", + "datacenter_label": 2, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-b-0:6422", + "guard_url": "http://rivet-engine-dc-b-0:6420" + }, + { + "name": "dc-c", + "datacenter_label": 3, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-c-0:6422", + "guard_url": "http://rivet-engine-dc-c-0:6420" + } + ] + }, + "postgres": { + "url": "postgresql://postgres:postgres@postgres-dc-c:5432/rivet_engine" + }, + "cache": { + "driver": "in_memory" + }, + "clickhouse": { + "http_url": "http://clickhouse:9300", + "native_url": "http://clickhouse:9301", + "username": "system", + "password": "default", + "provision_users": { + "vector": { + "username": "vector", + "password": "vector", + "role": "write" + } + }, + "secure": false + }, + "vector_http": { + "host": "vector-client-dc-c", + "port": 5022 + } +} \ No newline at end of file diff --git a/docker/dev-multidc-multinode/datacenters/dc-c/vector-client/vector.yaml b/docker/dev-multidc-multinode/datacenters/dc-c/vector-client/vector.yaml new file mode 100644 index 0000000000..717ddb2133 --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-c/vector-client/vector.yaml @@ -0,0 +1,31 @@ +# Vector Client Configuration for Datacenter: dc-c +# This Vector instance runs on each server to collect local logs and forward them +# to the central Vector server aggregator. + +api: + enabled: true + address: 0.0.0.0:8686 +sources: + http_events: + type: http_server + address: 0.0.0.0:5022 + encoding: ndjson +transforms: {} +sinks: + vector_server: + type: vector + inputs: + - http_events + address: vector-server-dc-c:6000 + version: '2' + buffer: + type: disk + max_size: 2147483648 + when_full: block + console_debug: + type: console + inputs: + - http_events + encoding: + codec: json + \ No newline at end of file diff --git a/docker/dev-multidc-multinode/datacenters/dc-c/vector-server/vector.yaml b/docker/dev-multidc-multinode/datacenters/dc-c/vector-server/vector.yaml new file mode 100644 index 0000000000..5dfdbff2f5 --- /dev/null +++ b/docker/dev-multidc-multinode/datacenters/dc-c/vector-server/vector.yaml @@ -0,0 +1,61 @@ +# Vector Server (Aggregator) Configuration +# This Vector instance acts as an aggregator that collects logs and metrics from all Vector clients +# across different datacenters and forwards them to ClickHouse and other sinks. + +api: + enabled: true + address: 0.0.0.0:8686 +sources: + vector: + type: vector + address: 0.0.0.0:6000 + version: '2' + tcp_json: + type: socket + mode: tcp + address: 0.0.0.0:6100 + decoding: + codec: json + http_json: + type: http_server + address: 0.0.0.0:6200 + encoding: json + vector_metrics: + type: internal_metrics + vector_logs: + type: internal_logs +transforms: + clickhouse_dynamic_events_filter: + type: filter + inputs: + - vector + condition: + type: vrl + source: .source == "clickhouse" + clickhouse_dynamic_events_transform: + type: remap + inputs: + - clickhouse_dynamic_events_filter + source: "# Extract and store metadata\n__database = .database\n__table = .table\n__columns = .columns\n\n# Create a new object with just the columns data\n. = {\n\t\"__database\": __database,\n\t\"__table\": __table,\n\t# By default insert namespace column since most tables include this\n\t\"namespace\": \"rivet\"\n}\n\t\n# Merge in the column data that should be inserted\n. = merge!(., __columns)\n" +sinks: + clickhouse_dynamic_events: + type: clickhouse + inputs: + - clickhouse_dynamic_events_transform + endpoint: http://clickhouse:9300 + database: '{{ __database }}' + table: '{{ __table }}' + compression: gzip + auth: + strategy: basic + user: system + password: default + batch: + max_events: 1000 + timeout_secs: 10 + console_vector_logs: + type: console + inputs: + - vector_logs + encoding: + codec: json diff --git a/docker/dev-multidc-multinode/docker-compose.yml b/docker/dev-multidc-multinode/docker-compose.yml new file mode 100644 index 0000000000..718843e72e --- /dev/null +++ b/docker/dev-multidc-multinode/docker-compose.yml @@ -0,0 +1,867 @@ +services: + clickhouse: + restart: unless-stopped + image: clickhouse/clickhouse-server:25.1.5 + volumes: + - clickhouse-data:/var/lib/clickhouse + - ./core/clickhouse/config.xml:/etc/clickhouse-server/config.d/config.xml + - ./core/clickhouse/users.xml:/etc/clickhouse-server/users.d/users.xml + - ./core/clickhouse/client-config.xml:/etc/clickhouse-client/config.xml + - ./core/clickhouse/init:/docker-entrypoint-initdb.d + environment: + - CLICKHOUSE_ALWAYS_RUN_INITDB_SCRIPTS=true + - CLICKHOUSE_USER=default + - CLICKHOUSE_PASSWORD=default + - CLICKHOUSE_HTTP_PORT=9300 + - CLICKHOUSE_TCP_PORT=9301 + networks: + - rivet-network-dc-a-to-core + - rivet-network-dc-b-to-core + - rivet-network-dc-c-to-core + - rivet-core-network + healthcheck: + test: + - CMD + - clickhouse-client + - '--host' + - 127.0.0.1 + - '--port' + - '9301' + - '--user' + - system + - '--password' + - default + - '--query' + - SELECT 1 + interval: 2s + timeout: 10s + retries: 10 + grafana: + image: grafana/grafana:11.5.2 + volumes: + - grafana-data:/var/lib/grafana + - ./core/grafana/grafana.ini:/etc/grafana/grafana.ini + - ./core/grafana/provisioning:/etc/grafana/provisioning + - ./core/grafana/dashboards:/var/lib/grafana/dashboards + environment: + - GF_INSTALL_PLUGINS=grafana-clickhouse-datasource + ports: + - '3100:3000' + networks: + - rivet-core-network + depends_on: + clickhouse: + condition: service_healthy + postgres-dc-a: + restart: unless-stopped + image: postgres:16-alpine + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=postgres + volumes: + - >- + ./datacenters/dc-a/postgres/init-db.sh:/docker-entrypoint-initdb.d/init-db.sh + - postgres-data-dc-a:/var/lib/postgresql/data + ports: + - '5432:5432' + healthcheck: + test: + - CMD-SHELL + - pg_isready -U postgres -d postgres + interval: 2s + timeout: 10s + retries: 10 + networks: + - rivet-network-dc-a + rivet-shell-dc-a: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: sleep infinity + stop_grace_period: 0s + depends_on: + postgres-dc-a: + condition: service_healthy + volumes: + - >- + ./datacenters/dc-a/rivet-engine/0/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network-dc-a + - rivet-network-dc-a-to-core + - rivet-network-dc-a-engine-peer + - rivet-network-dc-b-engine-peer + - rivet-network-dc-c-engine-peer + vector-server-dc-a: + restart: unless-stopped + image: timberio/vector:0.48.0-distroless-static + command: '-C /etc/vector' + volumes: + - vector-server-data-dc-a:/var/lib/vector + - ./datacenters/dc-a/vector-server:/etc/vector + networks: + - rivet-network-dc-a + - rivet-network-dc-a-to-core + depends_on: + clickhouse: + condition: service_healthy + vector-client-dc-a: + restart: unless-stopped + image: timberio/vector:0.48.0-distroless-static + command: '-C /etc/vector' + volumes: + - vector-client-data-dc-a:/var/lib/vector + - ./datacenters/dc-a/vector-client:/etc/vector + networks: + - rivet-network-dc-a + depends_on: + vector-server-dc-a: + condition: service_started + otel-collector-server-dc-a: + image: otel/opentelemetry-collector-contrib:latest + restart: unless-stopped + command: '--config=/etc/otel/config.yaml' + volumes: + - >- + ./datacenters/dc-a/otel-collector-server/config.yaml:/etc/otel/config.yaml:ro + environment: + - CLICKHOUSE_PASSWORD=default + depends_on: + clickhouse: + condition: service_healthy + networks: + - rivet-network-dc-a + - rivet-network-dc-a-to-core + otel-collector-client-dc-a: + image: otel/opentelemetry-collector-contrib:latest + restart: unless-stopped + command: '--config=/etc/otel/config.yaml' + volumes: + - >- + ./datacenters/dc-a/otel-collector-client/config.yaml:/etc/otel/config.yaml:ro + depends_on: + otel-collector-server-dc-a: + condition: service_started + networks: + - rivet-network-dc-a + rivet-engine-dc-a-0: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: /usr/bin/rivet-engine start + environment: + - RUST_LOG_ANSI_COLOR=1 + - RIVET_OTEL_ENABLED=1 + - RIVET_OTEL_SAMPLER_RATIO=1 + - RIVET_OTEL_GRPC_ENDPOINT=http://otel-collector-client-dc-a:4317 + stop_grace_period: 0s + depends_on: + vector-client-dc-a: + condition: service_started + otel-collector-client-dc-a: + condition: service_started + postgres-dc-a: + condition: service_healthy + volumes: + - >- + ./datacenters/dc-a/rivet-engine/0/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network-dc-a + - rivet-network-dc-a-to-core + - rivet-network-dc-a-engine-peer + - rivet-network-dc-b-engine-peer + - rivet-network-dc-c-engine-peer + ports: + - '6420:6420' + healthcheck: + test: + - CMD + - curl + - '-f' + - http://127.0.0.1:6421/health + interval: 2s + timeout: 10s + retries: 10 + start_period: 30s + rivet-engine-dc-a-1: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: /usr/bin/rivet-engine start + environment: + - RUST_LOG_ANSI_COLOR=1 + - RIVET_OTEL_ENABLED=1 + - RIVET_OTEL_SAMPLER_RATIO=1 + - RIVET_OTEL_GRPC_ENDPOINT=http://otel-collector-client-dc-a:4317 + stop_grace_period: 0s + depends_on: + vector-client-dc-a: + condition: service_started + otel-collector-client-dc-a: + condition: service_started + postgres-dc-a: + condition: service_healthy + volumes: + - >- + ./datacenters/dc-a/rivet-engine/1/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network-dc-a + - rivet-network-dc-a-to-core + - rivet-network-dc-a-engine-peer + - rivet-network-dc-b-engine-peer + - rivet-network-dc-c-engine-peer + healthcheck: + test: + - CMD + - curl + - '-f' + - http://127.0.0.1:6421/health + interval: 2s + timeout: 10s + retries: 10 + start_period: 30s + rivet-engine-dc-a-2: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: /usr/bin/rivet-engine start + environment: + - RUST_LOG_ANSI_COLOR=1 + - RIVET_OTEL_ENABLED=1 + - RIVET_OTEL_SAMPLER_RATIO=1 + - RIVET_OTEL_GRPC_ENDPOINT=http://otel-collector-client-dc-a:4317 + stop_grace_period: 0s + depends_on: + vector-client-dc-a: + condition: service_started + otel-collector-client-dc-a: + condition: service_started + postgres-dc-a: + condition: service_healthy + volumes: + - >- + ./datacenters/dc-a/rivet-engine/2/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network-dc-a + - rivet-network-dc-a-to-core + - rivet-network-dc-a-engine-peer + - rivet-network-dc-b-engine-peer + - rivet-network-dc-c-engine-peer + healthcheck: + test: + - CMD + - curl + - '-f' + - http://127.0.0.1:6421/health + interval: 2s + timeout: 10s + retries: 10 + start_period: 30s + runner-dc-a-0: + build: + context: ../.. + dockerfile: sdks/typescript/test-runner/Dockerfile + platform: linux/amd64 + restart: unless-stopped + environment: + - RIVET_ENDPOINT=http://rivet-engine-dc-a-0:6420 + - RUNNER_HOST=runner-dc-a-0 + stop_grace_period: 4s + ports: + - '5050:5050' + depends_on: + rivet-engine-dc-a-0: + condition: service_healthy + networks: + - rivet-network-dc-a + runner-dc-a-1: + build: + context: ../.. + dockerfile: sdks/typescript/test-runner/Dockerfile + platform: linux/amd64 + restart: unless-stopped + environment: + - RIVET_ENDPOINT=http://rivet-engine-dc-a-0:6420 + - RUNNER_HOST=runner-dc-a-1 + stop_grace_period: 4s + depends_on: + rivet-engine-dc-a-0: + condition: service_healthy + networks: + - rivet-network-dc-a + runner-dc-a-2: + build: + context: ../.. + dockerfile: sdks/typescript/test-runner/Dockerfile + platform: linux/amd64 + restart: unless-stopped + environment: + - RIVET_ENDPOINT=http://rivet-engine-dc-a-0:6420 + - RUNNER_HOST=runner-dc-a-2 + stop_grace_period: 4s + depends_on: + rivet-engine-dc-a-0: + condition: service_healthy + networks: + - rivet-network-dc-a + postgres-dc-b: + restart: unless-stopped + image: postgres:16-alpine + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=postgres + volumes: + - >- + ./datacenters/dc-b/postgres/init-db.sh:/docker-entrypoint-initdb.d/init-db.sh + - postgres-data-dc-b:/var/lib/postgresql/data + healthcheck: + test: + - CMD-SHELL + - pg_isready -U postgres -d postgres + interval: 2s + timeout: 10s + retries: 10 + networks: + - rivet-network-dc-b + rivet-shell-dc-b: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: sleep infinity + stop_grace_period: 0s + depends_on: + postgres-dc-b: + condition: service_healthy + volumes: + - >- + ./datacenters/dc-b/rivet-engine/0/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network-dc-b + - rivet-network-dc-b-to-core + - rivet-network-dc-a-engine-peer + - rivet-network-dc-b-engine-peer + - rivet-network-dc-c-engine-peer + vector-server-dc-b: + restart: unless-stopped + image: timberio/vector:0.48.0-distroless-static + command: '-C /etc/vector' + volumes: + - vector-server-data-dc-b:/var/lib/vector + - ./datacenters/dc-b/vector-server:/etc/vector + networks: + - rivet-network-dc-b + - rivet-network-dc-b-to-core + depends_on: + clickhouse: + condition: service_healthy + vector-client-dc-b: + restart: unless-stopped + image: timberio/vector:0.48.0-distroless-static + command: '-C /etc/vector' + volumes: + - vector-client-data-dc-b:/var/lib/vector + - ./datacenters/dc-b/vector-client:/etc/vector + networks: + - rivet-network-dc-b + depends_on: + vector-server-dc-b: + condition: service_started + otel-collector-server-dc-b: + image: otel/opentelemetry-collector-contrib:latest + restart: unless-stopped + command: '--config=/etc/otel/config.yaml' + volumes: + - >- + ./datacenters/dc-b/otel-collector-server/config.yaml:/etc/otel/config.yaml:ro + environment: + - CLICKHOUSE_PASSWORD=default + depends_on: + clickhouse: + condition: service_healthy + networks: + - rivet-network-dc-b + - rivet-network-dc-b-to-core + otel-collector-client-dc-b: + image: otel/opentelemetry-collector-contrib:latest + restart: unless-stopped + command: '--config=/etc/otel/config.yaml' + volumes: + - >- + ./datacenters/dc-b/otel-collector-client/config.yaml:/etc/otel/config.yaml:ro + depends_on: + otel-collector-server-dc-b: + condition: service_started + networks: + - rivet-network-dc-b + rivet-engine-dc-b-0: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: /usr/bin/rivet-engine start + environment: + - RUST_LOG_ANSI_COLOR=1 + - RIVET_OTEL_ENABLED=1 + - RIVET_OTEL_SAMPLER_RATIO=1 + - RIVET_OTEL_GRPC_ENDPOINT=http://otel-collector-client-dc-b:4317 + stop_grace_period: 0s + depends_on: + vector-client-dc-b: + condition: service_started + otel-collector-client-dc-b: + condition: service_started + postgres-dc-b: + condition: service_healthy + volumes: + - >- + ./datacenters/dc-b/rivet-engine/0/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network-dc-b + - rivet-network-dc-b-to-core + - rivet-network-dc-a-engine-peer + - rivet-network-dc-b-engine-peer + - rivet-network-dc-c-engine-peer + healthcheck: + test: + - CMD + - curl + - '-f' + - http://127.0.0.1:6421/health + interval: 2s + timeout: 10s + retries: 10 + start_period: 30s + rivet-engine-dc-b-1: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: /usr/bin/rivet-engine start + environment: + - RUST_LOG_ANSI_COLOR=1 + - RIVET_OTEL_ENABLED=1 + - RIVET_OTEL_SAMPLER_RATIO=1 + - RIVET_OTEL_GRPC_ENDPOINT=http://otel-collector-client-dc-b:4317 + stop_grace_period: 0s + depends_on: + vector-client-dc-b: + condition: service_started + otel-collector-client-dc-b: + condition: service_started + postgres-dc-b: + condition: service_healthy + volumes: + - >- + ./datacenters/dc-b/rivet-engine/1/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network-dc-b + - rivet-network-dc-b-to-core + - rivet-network-dc-a-engine-peer + - rivet-network-dc-b-engine-peer + - rivet-network-dc-c-engine-peer + healthcheck: + test: + - CMD + - curl + - '-f' + - http://127.0.0.1:6421/health + interval: 2s + timeout: 10s + retries: 10 + start_period: 30s + rivet-engine-dc-b-2: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: /usr/bin/rivet-engine start + environment: + - RUST_LOG_ANSI_COLOR=1 + - RIVET_OTEL_ENABLED=1 + - RIVET_OTEL_SAMPLER_RATIO=1 + - RIVET_OTEL_GRPC_ENDPOINT=http://otel-collector-client-dc-b:4317 + stop_grace_period: 0s + depends_on: + vector-client-dc-b: + condition: service_started + otel-collector-client-dc-b: + condition: service_started + postgres-dc-b: + condition: service_healthy + volumes: + - >- + ./datacenters/dc-b/rivet-engine/2/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network-dc-b + - rivet-network-dc-b-to-core + - rivet-network-dc-a-engine-peer + - rivet-network-dc-b-engine-peer + - rivet-network-dc-c-engine-peer + healthcheck: + test: + - CMD + - curl + - '-f' + - http://127.0.0.1:6421/health + interval: 2s + timeout: 10s + retries: 10 + start_period: 30s + runner-dc-b-0: + build: + context: ../.. + dockerfile: sdks/typescript/test-runner/Dockerfile + platform: linux/amd64 + restart: unless-stopped + environment: + - RIVET_ENDPOINT=http://rivet-engine-dc-b-0:6420 + - RUNNER_HOST=runner-dc-b-0 + stop_grace_period: 4s + depends_on: + rivet-engine-dc-b-0: + condition: service_healthy + networks: + - rivet-network-dc-b + runner-dc-b-1: + build: + context: ../.. + dockerfile: sdks/typescript/test-runner/Dockerfile + platform: linux/amd64 + restart: unless-stopped + environment: + - RIVET_ENDPOINT=http://rivet-engine-dc-b-0:6420 + - RUNNER_HOST=runner-dc-b-1 + stop_grace_period: 4s + depends_on: + rivet-engine-dc-b-0: + condition: service_healthy + networks: + - rivet-network-dc-b + runner-dc-b-2: + build: + context: ../.. + dockerfile: sdks/typescript/test-runner/Dockerfile + platform: linux/amd64 + restart: unless-stopped + environment: + - RIVET_ENDPOINT=http://rivet-engine-dc-b-0:6420 + - RUNNER_HOST=runner-dc-b-2 + stop_grace_period: 4s + depends_on: + rivet-engine-dc-b-0: + condition: service_healthy + networks: + - rivet-network-dc-b + postgres-dc-c: + restart: unless-stopped + image: postgres:16-alpine + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=postgres + volumes: + - >- + ./datacenters/dc-c/postgres/init-db.sh:/docker-entrypoint-initdb.d/init-db.sh + - postgres-data-dc-c:/var/lib/postgresql/data + healthcheck: + test: + - CMD-SHELL + - pg_isready -U postgres -d postgres + interval: 2s + timeout: 10s + retries: 10 + networks: + - rivet-network-dc-c + rivet-shell-dc-c: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: sleep infinity + stop_grace_period: 0s + depends_on: + postgres-dc-c: + condition: service_healthy + volumes: + - >- + ./datacenters/dc-c/rivet-engine/0/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network-dc-c + - rivet-network-dc-c-to-core + - rivet-network-dc-a-engine-peer + - rivet-network-dc-b-engine-peer + - rivet-network-dc-c-engine-peer + vector-server-dc-c: + restart: unless-stopped + image: timberio/vector:0.48.0-distroless-static + command: '-C /etc/vector' + volumes: + - vector-server-data-dc-c:/var/lib/vector + - ./datacenters/dc-c/vector-server:/etc/vector + networks: + - rivet-network-dc-c + - rivet-network-dc-c-to-core + depends_on: + clickhouse: + condition: service_healthy + vector-client-dc-c: + restart: unless-stopped + image: timberio/vector:0.48.0-distroless-static + command: '-C /etc/vector' + volumes: + - vector-client-data-dc-c:/var/lib/vector + - ./datacenters/dc-c/vector-client:/etc/vector + networks: + - rivet-network-dc-c + depends_on: + vector-server-dc-c: + condition: service_started + otel-collector-server-dc-c: + image: otel/opentelemetry-collector-contrib:latest + restart: unless-stopped + command: '--config=/etc/otel/config.yaml' + volumes: + - >- + ./datacenters/dc-c/otel-collector-server/config.yaml:/etc/otel/config.yaml:ro + environment: + - CLICKHOUSE_PASSWORD=default + depends_on: + clickhouse: + condition: service_healthy + networks: + - rivet-network-dc-c + - rivet-network-dc-c-to-core + otel-collector-client-dc-c: + image: otel/opentelemetry-collector-contrib:latest + restart: unless-stopped + command: '--config=/etc/otel/config.yaml' + volumes: + - >- + ./datacenters/dc-c/otel-collector-client/config.yaml:/etc/otel/config.yaml:ro + depends_on: + otel-collector-server-dc-c: + condition: service_started + networks: + - rivet-network-dc-c + rivet-engine-dc-c-0: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: /usr/bin/rivet-engine start + environment: + - RUST_LOG_ANSI_COLOR=1 + - RIVET_OTEL_ENABLED=1 + - RIVET_OTEL_SAMPLER_RATIO=1 + - RIVET_OTEL_GRPC_ENDPOINT=http://otel-collector-client-dc-c:4317 + stop_grace_period: 0s + depends_on: + vector-client-dc-c: + condition: service_started + otel-collector-client-dc-c: + condition: service_started + postgres-dc-c: + condition: service_healthy + volumes: + - >- + ./datacenters/dc-c/rivet-engine/0/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network-dc-c + - rivet-network-dc-c-to-core + - rivet-network-dc-a-engine-peer + - rivet-network-dc-b-engine-peer + - rivet-network-dc-c-engine-peer + healthcheck: + test: + - CMD + - curl + - '-f' + - http://127.0.0.1:6421/health + interval: 2s + timeout: 10s + retries: 10 + start_period: 30s + rivet-engine-dc-c-1: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: /usr/bin/rivet-engine start + environment: + - RUST_LOG_ANSI_COLOR=1 + - RIVET_OTEL_ENABLED=1 + - RIVET_OTEL_SAMPLER_RATIO=1 + - RIVET_OTEL_GRPC_ENDPOINT=http://otel-collector-client-dc-c:4317 + stop_grace_period: 0s + depends_on: + vector-client-dc-c: + condition: service_started + otel-collector-client-dc-c: + condition: service_started + postgres-dc-c: + condition: service_healthy + volumes: + - >- + ./datacenters/dc-c/rivet-engine/1/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network-dc-c + - rivet-network-dc-c-to-core + - rivet-network-dc-a-engine-peer + - rivet-network-dc-b-engine-peer + - rivet-network-dc-c-engine-peer + healthcheck: + test: + - CMD + - curl + - '-f' + - http://127.0.0.1:6421/health + interval: 2s + timeout: 10s + retries: 10 + start_period: 30s + rivet-engine-dc-c-2: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: /usr/bin/rivet-engine start + environment: + - RUST_LOG_ANSI_COLOR=1 + - RIVET_OTEL_ENABLED=1 + - RIVET_OTEL_SAMPLER_RATIO=1 + - RIVET_OTEL_GRPC_ENDPOINT=http://otel-collector-client-dc-c:4317 + stop_grace_period: 0s + depends_on: + vector-client-dc-c: + condition: service_started + otel-collector-client-dc-c: + condition: service_started + postgres-dc-c: + condition: service_healthy + volumes: + - >- + ./datacenters/dc-c/rivet-engine/2/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network-dc-c + - rivet-network-dc-c-to-core + - rivet-network-dc-a-engine-peer + - rivet-network-dc-b-engine-peer + - rivet-network-dc-c-engine-peer + healthcheck: + test: + - CMD + - curl + - '-f' + - http://127.0.0.1:6421/health + interval: 2s + timeout: 10s + retries: 10 + start_period: 30s + runner-dc-c-0: + build: + context: ../.. + dockerfile: sdks/typescript/test-runner/Dockerfile + platform: linux/amd64 + restart: unless-stopped + environment: + - RIVET_ENDPOINT=http://rivet-engine-dc-c-0:6420 + - RUNNER_HOST=runner-dc-c-0 + stop_grace_period: 4s + depends_on: + rivet-engine-dc-c-0: + condition: service_healthy + networks: + - rivet-network-dc-c + runner-dc-c-1: + build: + context: ../.. + dockerfile: sdks/typescript/test-runner/Dockerfile + platform: linux/amd64 + restart: unless-stopped + environment: + - RIVET_ENDPOINT=http://rivet-engine-dc-c-0:6420 + - RUNNER_HOST=runner-dc-c-1 + stop_grace_period: 4s + depends_on: + rivet-engine-dc-c-0: + condition: service_healthy + networks: + - rivet-network-dc-c + runner-dc-c-2: + build: + context: ../.. + dockerfile: sdks/typescript/test-runner/Dockerfile + platform: linux/amd64 + restart: unless-stopped + environment: + - RIVET_ENDPOINT=http://rivet-engine-dc-c-0:6420 + - RUNNER_HOST=runner-dc-c-2 + stop_grace_period: 4s + depends_on: + rivet-engine-dc-c-0: + condition: service_healthy + networks: + - rivet-network-dc-c +networks: + rivet-core-network: + driver: bridge + rivet-network-dc-a: + driver: bridge + rivet-network-dc-a-engine-peer: + driver: bridge + rivet-network-dc-a-to-core: + driver: bridge + rivet-network-dc-b: + driver: bridge + rivet-network-dc-b-engine-peer: + driver: bridge + rivet-network-dc-b-to-core: + driver: bridge + rivet-network-dc-c: + driver: bridge + rivet-network-dc-c-engine-peer: + driver: bridge + rivet-network-dc-c-to-core: + driver: bridge +volumes: + clickhouse-data: null + grafana-data: null + postgres-data-dc-a: null + vector-server-data-dc-a: null + vector-client-data-dc-a: null + postgres-data-dc-b: null + vector-server-data-dc-b: null + vector-client-data-dc-b: null + postgres-data-dc-c: null + vector-server-data-dc-c: null + vector-client-data-dc-c: null diff --git a/docker/dev-multidc/.gitattributes b/docker/dev-multidc/.gitattributes new file mode 100644 index 0000000000..447edeb5c2 --- /dev/null +++ b/docker/dev-multidc/.gitattributes @@ -0,0 +1 @@ +. linguist-generated=true diff --git a/docker/dev-multidc/README.md b/docker/dev-multidc/README.md new file mode 100644 index 0000000000..c8493b6eab --- /dev/null +++ b/docker/dev-multidc/README.md @@ -0,0 +1,86 @@ +# dev-multidc - Auto-generated Docker Compose Template + +> ! **Auto-generated**: This directory and its contents are automatically generated by `docker/template/`. Do not edit these files directly as your changes will be overwritten. + +## Overview + +This Docker Compose configuration provides a complete development environment for Rivet with the following services: + +- **Rivet Engine**: Main orchestration service +- **Rivet Shell**: Interactive shell for debugging +- **Runner**: Executes user code +- **ClickHouse**: Analytics and time-series database +- **PostgreSQL**: Relational database +- **Vector Server**: Log aggregation and processing +- **OpenTelemetry Collector**: Observability data collection + +## Port Configuration + +| Service | Port(s) | Description | +|---------|---------|-------------| +| Rivet Engine | 6420 | Public endpoint | +| Runner | 5050 | Code execution service | +| PostgreSQL | 5432 | Database | +| ClickHouse HTTP | 9300 | Database HTTP interface | +| ClickHouse Native | 9301 | Database native protocol | +| OpenTelemetry gRPC | 4317 | OTLP gRPC endpoint | +| OpenTelemetry HTTP | 4318 | OTLP HTTP endpoint | + +## Template Configuration + +**Template Name**: `dev-multidc` +**Base Port**: `6420` +**Network Mode**: `bridge` + +### Datacenters +- **1**: 1 engine(s), 1 runner(s) +- **2**: 1 engine(s), 1 runner(s) +- **3**: 1 engine(s), 1 runner(s) + +## Usage + +1. Start all services: + ```bash + docker-compose up -d + ``` + +2. Check service health: + ```bash + docker-compose ps + ``` + +3. View logs: + ```bash + docker-compose logs -f [service-name] + ``` + +4. Stop all services: + ```bash + docker-compose down + ``` + +## Generated Files + +This template generates the following files and directories: +- `docker-compose.yml` - Main Docker Compose configuration +- `core/` - Core services shared across datacenters: + - `clickhouse/` - ClickHouse configuration and initialization + - `vector-server/` - Vector aggregator configuration + - `otel-collector-server/` - OpenTelemetry Collector server configuration +- `datacenters/` - Datacenter-specific configurations: + - `1/` - Configuration for datacenter 1: + - `postgres/` - PostgreSQL setup scripts + - `rivet-engine/` - Rivet Engine configuration + - `vector-client/` - Vector client configuration + - `otel-collector-client/` - OpenTelemetry Collector client configuration + - `2/` - Configuration for datacenter 2: + - `postgres/` - PostgreSQL setup scripts + - `rivet-engine/` - Rivet Engine configuration + - `vector-client/` - Vector client configuration + - `otel-collector-client/` - OpenTelemetry Collector client configuration + - `3/` - Configuration for datacenter 3: + - `postgres/` - PostgreSQL setup scripts + - `rivet-engine/` - Rivet Engine configuration + - `vector-client/` - Vector client configuration + - `otel-collector-client/` - OpenTelemetry Collector client configuration +- `README.md` - This file diff --git a/docker/dev-multidc/core/clickhouse/client-config.xml b/docker/dev-multidc/core/clickhouse/client-config.xml new file mode 100644 index 0000000000..72f9850f4e --- /dev/null +++ b/docker/dev-multidc/core/clickhouse/client-config.xml @@ -0,0 +1,5 @@ + + + 9301 + 127.0.0.1 + \ No newline at end of file diff --git a/docker/dev-multidc/core/clickhouse/config.xml b/docker/dev-multidc/core/clickhouse/config.xml new file mode 100644 index 0000000000..e7ccd0480b --- /dev/null +++ b/docker/dev-multidc/core/clickhouse/config.xml @@ -0,0 +1,52 @@ + + + + debug + /var/log/clickhouse-server/clickhouse-server.log + /var/log/clickhouse-server/clickhouse-server.err.log + 1000M + 10 + + + :: + 9300 + 9301 + + + 9440 + 9010 + + 9009 + + 4096 + 3 + 100 + 8589934592 + 5368709120 + + /var/lib/clickhouse/ + /var/lib/clickhouse/tmp/ + /var/lib/clickhouse/user_files/ + /var/lib/clickhouse/access/ + + users.xml + default + default + UTC + + + + + + 3600 + 3600 + 60 + + + system + query_log
+ 7500 +
+ + *_dictionary.xml +
diff --git a/docker/dev-multidc/core/clickhouse/init/01-create-otel-table.sql b/docker/dev-multidc/core/clickhouse/init/01-create-otel-table.sql new file mode 100644 index 0000000000..2c7b9f7957 --- /dev/null +++ b/docker/dev-multidc/core/clickhouse/init/01-create-otel-table.sql @@ -0,0 +1,107 @@ +CREATE DATABASE IF NOT EXISTS otel; + +CREATE TABLE IF NOT EXISTS otel.otel_logs ( + Timestamp DateTime64(9) CODEC(Delta, ZSTD(1)), + ObservedTimestamp DateTime64(9) CODEC(Delta, ZSTD(1)), + TraceId String CODEC(ZSTD(1)), + SpanId String CODEC(ZSTD(1)), + TraceFlags UInt32 CODEC(ZSTD(1)), + SeverityText LowCardinality(String) CODEC(ZSTD(1)), + SeverityNumber Int32 CODEC(ZSTD(1)), + ServiceName LowCardinality(String) CODEC(ZSTD(1)), + Body String CODEC(ZSTD(1)), + ResourceSchemaUrl String CODEC(ZSTD(1)), + ResourceAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ScopeSchemaUrl String CODEC(ZSTD(1)), + ScopeName String CODEC(ZSTD(1)), + ScopeVersion String CODEC(ZSTD(1)), + ScopeAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + LogAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + INDEX idx_trace_id TraceId TYPE bloom_filter(0.001) GRANULARITY 1, + INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_key mapKeys(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_value mapValues(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_log_attr_key mapKeys(LogAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_log_attr_value mapValues(LogAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_body Body TYPE tokenbf_v1(32768, 3, 0) GRANULARITY 1 +) ENGINE = MergeTree() +PARTITION BY toDate(Timestamp) +ORDER BY (ServiceName, SeverityText, toUnixTimestamp(Timestamp), TraceId) +TTL toDateTime(Timestamp) + toIntervalDay(3) +SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1; + +CREATE TABLE IF NOT EXISTS otel.otel_traces ( + Timestamp DateTime64(9) CODEC(Delta, ZSTD(1)), + TraceId String CODEC(ZSTD(1)), + SpanId String CODEC(ZSTD(1)), + ParentSpanId String CODEC(ZSTD(1)), + TraceState String CODEC(ZSTD(1)), + SpanName LowCardinality(String) CODEC(ZSTD(1)), + SpanKind LowCardinality(String) CODEC(ZSTD(1)), + ServiceName LowCardinality(String) CODEC(ZSTD(1)), + ResourceAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ScopeName String CODEC(ZSTD(1)), + ScopeVersion String CODEC(ZSTD(1)), + SpanAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + Duration Int64 CODEC(ZSTD(1)), + StatusCode LowCardinality(String) CODEC(ZSTD(1)), + StatusMessage String CODEC(ZSTD(1)), + Events Nested ( + Timestamp DateTime64(9), + Name LowCardinality(String), + Attributes Map(LowCardinality(String), String) + ) CODEC(ZSTD(1)), + Links Nested ( + TraceId String, + SpanId String, + TraceState String, + Attributes Map(LowCardinality(String), String) + ) CODEC(ZSTD(1)), + INDEX idx_trace_id TraceId TYPE bloom_filter(0.001) GRANULARITY 1, + INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_span_attr_key mapKeys(SpanAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_span_attr_value mapValues(SpanAttributes) TYPE bloom_filter(0.01) GRANULARITY 1 +) ENGINE = MergeTree() +PARTITION BY toDate(Timestamp) +ORDER BY (ServiceName, SpanName, toUnixTimestamp(Timestamp), TraceId) +TTL toDateTime(Timestamp) + toIntervalDay(7) +SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1; + +CREATE TABLE IF NOT EXISTS otel.otel_metrics ( + ResourceAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ResourceSchemaUrl String CODEC(ZSTD(1)), + ScopeName String CODEC(ZSTD(1)), + ScopeVersion String CODEC(ZSTD(1)), + ScopeAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ScopeDroppedAttrCount UInt32 CODEC(ZSTD(1)), + ScopeSchemaUrl String CODEC(ZSTD(1)), + MetricName String CODEC(ZSTD(1)), + MetricDescription String CODEC(ZSTD(1)), + MetricUnit String CODEC(ZSTD(1)), + Attributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + StartTimeUnix DateTime64(9) CODEC(Delta, ZSTD(1)), + TimeUnix DateTime64(9) CODEC(Delta, ZSTD(1)), + Value Float64 CODEC(ZSTD(1)), + Flags UInt32 CODEC(ZSTD(1)), + Exemplars Nested ( + FilteredAttributes Map(LowCardinality(String), String), + TimeUnix DateTime64(9), + Value Float64, + SpanId String, + TraceId String + ) CODEC(ZSTD(1)), + AggTemp Int32 CODEC(ZSTD(1)), + IsMonotonic Bool CODEC(ZSTD(1)), + INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_key mapKeys(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_value mapValues(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_attr_key mapKeys(Attributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_attr_value mapValues(Attributes) TYPE bloom_filter(0.01) GRANULARITY 1 +) ENGINE = MergeTree() +PARTITION BY toDate(TimeUnix) +ORDER BY (MetricName, Attributes, toUnixTimestamp(TimeUnix)) +TTL toDateTime(TimeUnix) + toIntervalDay(30) +SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1; diff --git a/docker/dev-multidc/core/clickhouse/users.xml b/docker/dev-multidc/core/clickhouse/users.xml new file mode 100644 index 0000000000..743cada261 --- /dev/null +++ b/docker/dev-multidc/core/clickhouse/users.xml @@ -0,0 +1,35 @@ + + + + + default + + ::/0 + + default + default + 1 + + + + + + 10000000000 + 0 + random + + + + + + + 3600 + 0 + 0 + 0 + 0 + 0 + + + + diff --git a/docker/dev-multidc/core/grafana/dashboards/api.json b/docker/dev-multidc/core/grafana/dashboards/api.json new file mode 100644 index 0000000000..34004bf134 --- /dev/null +++ b/docker/dev-multidc/core/grafana/dashboards/api.json @@ -0,0 +1,1172 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 7, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 24, + "panels": [], + "title": "API", + "type": "row" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 26, + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_api_request_duration'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Request Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 27, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_api_request_pending'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Requests Pending", + "transformations": [ + { + "id": "groupingToMatrix", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 10 + }, + "id": 32, + "interval": "15s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n sum(Sum) / sum(Count) as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nHAVING sum(Count) > 0\nORDER BY time", + "refId": "A" + } + ], + "title": "Duration (avg)", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 10 + }, + "id": 33, + "interval": "15s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label, bounds, idx\nORDER BY time", + "refId": "A" + } + ], + "title": "Duration (p95)", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "bounds" + } + }, + { + "id": "convertFieldType", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 16, + "y": 10 + }, + "id": 34, + "interval": "15s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n Attributes['method'] as method,\n Attributes['path'] as path,\n histogramQuantile(arrayZip(ExplicitBounds, BucketCounts), 0.99) as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND Attributes['watch'] = '0'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, method, path\nORDER BY time", + "refId": "A" + } + ], + "title": "Duration (p99)", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 19 + }, + "id": 25, + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n sum(Value) / $__interval_ms * 1000 as value\n -- (\n -- SELECT\n -- sum(Value) / $__interval_ms * 1000 as value\n -- FROM otel.otel_metrics_sum\n -- WHERE MetricName = 'rivet_api_request_total'\n -- AND $__conditionalAll(Attributes['path'], $path)\n -- AND $__conditionalAll(Attributes['method'], $method)\n -- AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n -- AND $__timeFilter(TimeUnix)\n -- ) as prev_value\n -- lagInFrame(value, 1, value) OVER (ORDER BY time) as previous_value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_api_request_total'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Request Rate", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 19 + }, + "id": 28, + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Name", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}: {{status}} ({{error_code}})", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path'], ': ',\n Attributes['status'], ' (',\n Attributes['error_code'], ')'\n ) as label,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_api_request_errors'\n AND Attributes['status'] LIKE '4%'\n AND Attributes['error_code'] NOT IN ('API_CANCELLED', 'CAPTCHA_CAPTCHA_REQUIRED')\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Error Rate (4xx)", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\label" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 16, + "y": 19 + }, + "id": 31, + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}: {{status}} ({{error_code}})", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path'], ': ',\n Attributes['error_code'], ' (',\n Attributes['status'], ')'\n ) as label,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_api_request_errors'\n AND Attributes['status'] LIKE '5%'\n AND Attributes['error_code']-- NOT IN ('API_CANCELLED', 'CAPTCHA_CAPTCHA_REQUIRED')\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Error Rate (5xx)", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "log": 2, + "type": "log" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "percent" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 28 + }, + "id": 35, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{method}} {{path}}: {{status}} {{error_code}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['method'] as method,\n Attributes['path'] as path,\n Attributes['status'] as status,\n Attributes['error_code'] as error_code,\n sum(Count) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND (Attributes['status'] = '200' OR Attributes['status'] LIKE '5%')\n AND Attributes['error_code']-- NOT IN ('API_CANCELLED', 'CAPTCHA_CAPTCHA_REQUIRED')\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, method, path, status, error_code\nORDER BY time", + "refId": "A" + } + ], + "title": "200 vs 5xx (4xx excluded)", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "30s", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request_errors' ORDER BY datacenter_id", + "includeAll": true, + "label": "Datacenter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request_errors' ORDER BY datacenter_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['path'] as path FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) ORDER BY path", + "includeAll": true, + "label": "Path", + "multi": true, + "name": "path", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['path'] as path FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) ORDER BY path", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['method'] as method FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) AND $__conditionalAll(Attributes['path'], $path) ORDER BY method", + "includeAll": true, + "label": "Method", + "multi": true, + "name": "method", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['method'] as method FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) AND $__conditionalAll(Attributes['path'], $path) ORDER BY method", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-24h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "API", + "uid": "feg8y72gpm2o0c", + "version": 1, + "weekStart": "" +} diff --git a/docker/dev-multidc/core/grafana/dashboards/cache.json b/docker/dev-multidc/core/grafana/dashboards/cache.json new file mode 100644 index 0000000000..5d762023ea --- /dev/null +++ b/docker/dev-multidc/core/grafana/dashboards/cache.json @@ -0,0 +1,1176 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 4, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 10, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n CASE\n WHEN ResourceAttributes['datacenter_id'] != '' AND ResourceAttributes['server_id'] != '' THEN concat(ResourceAttributes['datacenter_id'], ' - ', ResourceAttributes['server_id'])\n ELSE 'Route Cache Size'\n END as label,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_route_cache_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Route Cache Size", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\label" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 11, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_rate_limiter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Rate Limiters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 12, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_in_flight_counter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "In-Flight Counters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 8 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_tcp_connection_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active TCP Connections", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 8 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_tcp_connection'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "TCP Connection Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 8 + }, + "id": 1, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_tcp_connection_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "TCP Connection Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 16 + }, + "id": 7, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_proxy_request_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Proxy Requests", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 16 + }, + "id": 8, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_proxy_request'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Proxy Request Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 16 + }, + "id": 9, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_proxy_request_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Proxy Request Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 24 + }, + "id": 6, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_resolve_route_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Resolve Route Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "description": "", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "description": "", + "includeAll": true, + "label": "Dataceter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "description": "", + "includeAll": true, + "label": "Server ID", + "multi": true, + "name": "server_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Rivet Guard", + "uid": "cen785ige8fswd", + "version": 1, + "weekStart": "" +} diff --git a/docker/dev-multidc/core/grafana/dashboards/futures.json b/docker/dev-multidc/core/grafana/dashboards/futures.json new file mode 100644 index 0000000000..0c992c4bcb --- /dev/null +++ b/docker/dev-multidc/core/grafana/dashboards/futures.json @@ -0,0 +1,208 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_instrumented_future_duration'\n AND $__conditionalAll(Attributes['name'], $name)\n AND $__conditionalAll(Attributes['location'], $location)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Instrumented Future Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "30s", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['name'] as name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY name", + "includeAll": true, + "label": "Name", + "multi": true, + "name": "name", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['name'] as name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY name", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['location'] as location FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY location", + "includeAll": true, + "label": "Location", + "multi": true, + "name": "location", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['location'] as location FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY location", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Futures", + "version": 0, + "weekStart": "" +} \ No newline at end of file diff --git a/docker/dev-multidc/core/grafana/dashboards/gasoline.json b/docker/dev-multidc/core/grafana/dashboards/gasoline.json new file mode 100644 index 0000000000..bac8c7b6da --- /dev/null +++ b/docker/dev-multidc/core/grafana/dashboards/gasoline.json @@ -0,0 +1,2583 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": 3, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{workflow_name}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_active'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Running Workflows", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 3, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{workflow_name}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_sleeping'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Sleeping Workflows", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 1, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{workflow_name}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_dead'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Dead Workflows", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 6, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "({{workflow_name}}) {{error_code}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n Attributes['error_code'] as error_code,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_dead'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name, error_code\nORDER BY time", + "refId": "A" + } + ], + "title": "Dead Workflow Errors", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "__auto", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n count(*) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_worker_last_ping'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Workers", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "datacenter_id", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\datacenter_id" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 4, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{signal_name}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['signal_name'] as signal_name,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_signal_pending'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, signal_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Pending Signals", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "signal_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\signal_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 10, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size", + "value": "" + }, + "yBuckets": { + "mode": "size", + "scale": { + "log": 2, + "type": "log" + }, + "value": "" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "hide": false, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_signal_recv_lag'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Signal Receive Lag", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 24 + }, + "id": 11, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_signal_pull_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY\n Time, le\nORDER BY\n Time, le", + "refId": "A" + } + ], + "title": "Pull Signals Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 32 + }, + "id": 13, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "instant": false, + "legendFormat": "{{worker_instance_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['worker_instance_id'] as worker_instance_id,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_last_pull_workflows_duration'\n AND ResourceAttributes['cluster_id'] LIKE '${cluster_id:regex}'\n AND ResourceAttributes['datacenter_id'] LIKE '${datacenter_id:regex}'\n AND $__timeFilter(TimeUnix)\nGROUP BY time, worker_instance_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Last Pull Workflows Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "worker_instance_id", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\worker_instance_id" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 32 + }, + "id": 14, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "instant": false, + "legendFormat": "{{worker_instance_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['worker_instance_id'] as worker_instance_id,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_last_pull_workflows_history_duration'\n AND ResourceAttributes['cluster_id'] LIKE '${cluster_id:regex}'\n AND ResourceAttributes['datacenter_id'] LIKE '${datacenter_id:regex}'\n AND $__timeFilter(TimeUnix)\nGROUP BY time, worker_instance_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Last Pull Workflows History Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "worker_instance_id", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\worker_instance_id" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 40 + }, + "id": 23, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_pull_workflows_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Pull Workflows Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 40 + }, + "id": 24, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_pull_workflows_history_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Pull Workflows History Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 48 + }, + "id": 16, + "panels": [], + "title": "Steps", + "type": "row" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 49 + }, + "id": 12, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_activity_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Activity Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 49 + }, + "id": 9, + "interval": "15s", + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{activity_name}}: {{error_code}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['activity_name'] as activity_name,\n Attributes['error_code'] as error_code,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_gasoline_activity_errors'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, activity_name, error_code\nORDER BY time", + "refId": "A" + } + ], + "title": "Activity Error Rate", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "activity_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\activity_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 58 + }, + "id": 21, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_loop_iteration_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Loop Upsert Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ev/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 58 + }, + "id": 25, + "interval": "15s", + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "legendFormat": "{{workflow_name}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n sum(Count) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_gasoline_loop_iteration_duration'\n AND Attributes['workflow_name'] LIKE '${workflow_name:regex}'\n AND ResourceAttributes['cluster_id'] LIKE '${cluster_id:regex}'\n AND ResourceAttributes['datacenter_id'] LIKE '${datacenter_id:regex}'\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Loop Events Per Second", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 67 + }, + "id": 17, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_message_send_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Message Send Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 67 + }, + "id": 20, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_signal_send_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Signal Send Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 76 + }, + "id": 22, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_find_workflows_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Find Workflows Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 76 + }, + "id": 19, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_workflow_dispatch_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Sub Workflow Dispatch Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "5s", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY cluster_id", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY cluster_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY datacenter_id", + "includeAll": true, + "label": "Datacenter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY datacenter_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['workflow_name'] as workflow_name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_gasoline_signal_recv_lag' ORDER BY workflow_name", + "includeAll": true, + "label": "Workflow Name", + "multi": true, + "name": "workflow_name", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['workflow_name'] as workflow_name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_gasoline_signal_recv_lag' ORDER BY workflow_name", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Gasoline", + "uid": "636d22f9-d18f-4086-8b45-7c50886a105c", + "version": 1, + "weekStart": "" +} diff --git a/docker/dev-multidc/core/grafana/dashboards/guard.json b/docker/dev-multidc/core/grafana/dashboards/guard.json new file mode 100644 index 0000000000..fb657d441b --- /dev/null +++ b/docker/dev-multidc/core/grafana/dashboards/guard.json @@ -0,0 +1,1150 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 115, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 10, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_route_cache_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Route Cache Size", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 11, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_rate_limiter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Rate Limiters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 12, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_in_flight_counter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "In-Flight Counters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 8 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_tcp_connection_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active TCP Connections", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 8 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_tcp_connection'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "TCP Connection Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 8 + }, + "id": 1, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_tcp_connection_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "TCP Connection Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 16 + }, + "id": 7, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_proxy_request_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Proxy Requests", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 16 + }, + "id": 8, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_proxy_request'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Proxy Request Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 16 + }, + "id": 9, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_proxy_request_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Proxy Request Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 24 + }, + "id": 6, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_resolve_route_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Resolve Route Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "description": "", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "description": "", + "includeAll": true, + "label": "Dataceter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "description": "", + "includeAll": true, + "label": "Server ID", + "multi": true, + "name": "server_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Rivet Guard", + "uid": "cen785ige8fswd", + "version": 1, + "weekStart": "" +} diff --git a/docker/dev-multidc/core/grafana/dashboards/tokio.json b/docker/dev-multidc/core/grafana/dashboards/tokio.json new file mode 100644 index 0000000000..efa5e4b49f --- /dev/null +++ b/docker/dev-multidc/core/grafana/dashboards/tokio.json @@ -0,0 +1,1009 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": 81, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 24, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_global_queue_depth'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Global Queue Depth", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 27, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_worker_local_queue_depth'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Worker Queue Depth", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 11, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_tokio_task_poll_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Task Poll Times", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 26, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_worker_overflow_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Worker Overflow Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 23, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_future_schedule_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Future Schedule Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 25, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_thread_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Thread Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "tasks/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 28, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_tokio_task'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Task Spawn Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 24 + }, + "id": 29, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_active_task_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Tasks", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "5s", + "schemaVersion": 40, + "templating": { + "list": [ + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY cluster_id", + "description": "", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY cluster_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY datacenter_id", + "description": "", + "includeAll": true, + "label": "Dataceter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY datacenter_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY server_id", + "description": "", + "includeAll": true, + "label": "Server ID", + "multi": true, + "name": "server_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY server_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['pool_type'] as pool_type FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY pool_type", + "includeAll": true, + "label": "Pool", + "multi": true, + "name": "pool_type", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['pool_type'] as pool_type FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY pool_type", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Tokio", + "uid": "636d22f9-d18f-4086-8b45-7c50886a105d", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/docker/dev-multidc/core/grafana/dashboards/traces.json b/docker/dev-multidc/core/grafana/dashboards/traces.json new file mode 100644 index 0000000000..64f6b552c9 --- /dev/null +++ b/docker/dev-multidc/core/grafana/dashboards/traces.json @@ -0,0 +1,979 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 21, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 9, + "panels": [], + "title": "Traces", + "type": "row" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "bars", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 0, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 1 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-traces" + }, + "editorType": "sql", + "format": 0, + "meta": { + "builderOptions": { + "aggregates": [ + { + "aggregateType": "count", + "column": "" + } + ], + "columns": [ + { + "hint": "time", + "name": "Timestamp", + "type": "DateTime64(9)" + } + ], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "hint": "time", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "ServiceName" + ], + "limit": 10000, + "mode": "trend", + "orderBy": [], + "queryType": "timeseries", + "table": "otel_traces" + } + }, + "pluginVersion": "4.0.6", + "queryType": "timeseries", + "rawSql": "SELECT\r\n $__timeInterval(Timestamp) as time,\r\n ServiceName,\r\n count() as ` `\r\nFROM otel.otel_traces\r\nWHERE\r\n ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )\r\n AND $__conditionalAll(ServiceName, $service_name)\r\n AND $__conditionalAll(SpanName, $span_name)\r\n AND (($ray_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['ray_id'], $ray_id))\r\n AND (($workflow_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['workflow_id'], $workflow_id))\r\nGROUP BY ServiceName, time\r\nORDER BY time ASC\r\nLIMIT 100000\r\n", + "refId": "A" + } + ], + "title": "Traces per Service", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Trace ID" + }, + "properties": [ + { + "id": "custom.width", + "value": 77 + }, + { + "id": "links", + "value": [ + { + "title": "__value.raw", + "url": "/d/8klBUGfVk/otel-traces?${__url_time_range}&${service_name:queryparam}&var-trace_id=${__value.raw}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Service Name" + }, + "properties": [ + { + "id": "custom.width", + "value": 130 + }, + { + "id": "links", + "value": [ + { + "title": "__value.raw", + "url": "/d/8klBUGfVk/otel-traces?${__url_time_range}&${trace_id:queryparam}&var-serviceName=${__value.raw}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Duration" + }, + "properties": [ + { + "id": "unit", + "value": "ms" + }, + { + "id": "custom.cellOptions", + "value": { + "mode": "lcd", + "type": "gauge", + "valueDisplayMode": "text" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "timestamp" + }, + "properties": [ + { + "id": "custom.width", + "value": 216 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Service Tags" + }, + "properties": [ + { + "id": "custom.inspect", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "timestamp" + }, + "properties": [ + { + "id": "custom.width", + "value": 248 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "timestamp" + }, + "properties": [ + { + "id": "custom.width", + "value": 234 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": " " + }, + "properties": [ + { + "id": "custom.width", + "value": 49 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Span Name" + }, + "properties": [ + { + "id": "custom.width", + "value": 140 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Ts" + }, + "properties": [ + { + "id": "custom.width", + "value": 168 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "URI/workflow_id/actor_id" + }, + "properties": [ + { + "id": "custom.width", + "value": 920 + } + ] + } + ] + }, + "gridPos": { + "h": 13, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 4, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Duration" + } + ] + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorType": "sql", + "format": 1, + "meta": { + "builderOptions": { + "columns": [], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "queryType": "table", + "table": "otel_traces" + } + }, + "pluginVersion": "4.9.0", + "queryType": "table", + "rawSql": "SELECT\r\n (argMin(StatusCode, Timestamp) = 'Error' ? '⚠️' : '') as ` `,\r\n min(Timestamp) as Ts,\r\n TraceId as `Trace ID`,\r\n argMin(ServiceName, Timestamp) as `Service Name`,\r\n argMin(SpanName, Timestamp) as `Span Name`,\r\n argMin(coalesce(NULLIF(SpanAttributes['uri'], ''), NULLIF(SpanAttributes['workflow_id'], ''), SpanAttributes['actor_id']), Timestamp) as `URI/workflow_id/actor_id`,\r\n divide(max(Duration), 1000000) as Duration\r\nFROM otel.otel_traces\r\nWHERE\r\n $__conditionalAll(ServiceName, $service_name)\r\n AND $__conditionalAll(SpanName, $span_name)\r\n AND (($ray_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['ray_id'], $ray_id))\r\n AND (($workflow_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['workflow_id'], $workflow_id))\r\n AND ServiceName != 'loadgenerator'\r\n AND ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )\r\nGROUP BY TraceId\r\nORDER BY Duration DESC\r\nLIMIT 100\r\n", + "refId": "A" + } + ], + "title": "Traces", + "type": "table" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, + "gridPos": { + "h": 17, + "w": 24, + "x": 0, + "y": 23 + }, + "id": 6, + "options": { + "spanFilters": { + "criticalPathOnly": false, + "matchesOnly": false, + "serviceNameOperator": "=", + "spanNameOperator": "=" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "builderOptions": { + "columns": [ + { + "hint": "trace_id", + "name": "TraceId" + }, + { + "hint": "trace_span_id", + "name": "SpanId" + }, + { + "hint": "trace_parent_span_id", + "name": "ParentSpanId" + }, + { + "hint": "trace_service_name", + "name": "ServiceName" + }, + { + "hint": "trace_operation_name", + "name": "SpanName" + }, + { + "hint": "time", + "name": "Timestamp" + }, + { + "hint": "trace_duration_time", + "name": "Duration" + }, + { + "hint": "trace_tags", + "name": "SpanAttributes" + }, + { + "hint": "trace_service_tags", + "name": "ResourceAttributes" + }, + { + "hint": "trace_status_code", + "name": "StatusCode" + } + ], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "hint": "time", + "key": "", + "operator": "WITH IN DASHBOARD TIME RANGE", + "type": "datetime" + }, + { + "condition": "AND", + "filterType": "custom", + "hint": "trace_duration_time", + "key": "", + "operator": ">", + "type": "UInt64", + "value": 0 + }, + { + "condition": "AND", + "filterType": "custom", + "hint": "trace_service_name", + "key": "", + "operator": "IS ANYTHING", + "type": "string", + "value": "" + } + ], + "limit": 1000, + "meta": { + "isTraceIdMode": true, + "otelEnabled": true, + "otelVersion": "latest", + "traceDurationUnit": "nanoseconds", + "traceId": "${trace_id}" + }, + "mode": "list", + "orderBy": [ + { + "default": true, + "dir": "DESC", + "hint": "time", + "name": "" + }, + { + "default": true, + "dir": "DESC", + "hint": "trace_duration_time", + "name": "" + } + ], + "queryType": "traces", + "table": "otel_traces" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-traces" + }, + "editorType": "builder", + "format": 3, + "meta": { + "builderOptions": { + "columns": [], + "database": "", + "limit": 100, + "mode": "list", + "queryType": "table", + "table": "" + } + }, + "pluginVersion": "4.0.6", + "queryType": "traces", + "rawSql": "WITH\n\t(SELECT min(Start) FROM otel.otel_traces_trace_id_ts WHERE $__conditionalAll(TraceId, $trace_id)) as trace_start,\n\t(SELECT max(End) + 1 FROM otel.otel_traces_trace_id_ts WHERE $__conditionalAll(TraceId, $trace_id)) as trace_end\nSELECT\n\tTraceId as traceID,\n\tSpanId as spanID,\n\tParentSpanId as parentSpanID,\n\tServiceName as serviceName,\n\tSpanName as operationName, Timestamp as startTime,\n\tmultiply(Duration, 0.000001) as duration,\n\tarrayMap(key -> map('key', key, 'value', SpanAttributes[key]), mapKeys(SpanAttributes)) as tags,\n\tarrayMap(key -> map('key', key, 'value', ResourceAttributes[key]), mapKeys(ResourceAttributes)) as serviceTags,\n\tarrayMap((name, timestamp, attributes) -> tuple(name, toString(multiply(toUnixTimestamp64Nano(timestamp), 0.000001)), arrayMap( key -> map('key', key, 'value', attributes[key]), mapKeys(attributes)))::Tuple(name String, timestamp String, fields Array(Map(String, String))), `Events.Name`, `Events.Timestamp`, `Events.Attributes`) AS logs,\n\tarrayMap((traceID, spanID, attributes) -> tuple(traceID, spanID, arrayMap(key -> map('key', key, 'value', attributes[key]), mapKeys(attributes)))::Tuple(traceID String, spanID String, tags Array(Map(String, String))), `Links.TraceId`, `Links.SpanId`, `Links.Attributes`) AS references\nFROM otel.otel_traces\nWHERE\n\t$__conditionalAll(traceID, $trace_id) AND startTime >= trace_start AND startTime <= trace_end AND ( Duration > 0 )\nORDER BY Timestamp DESC, Duration DESC\nLIMIT 1000", + "refId": "A" + } + ], + "title": "Trace Details", + "type": "traces" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "bars", + "fillOpacity": 24, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 8, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-traces" + }, + "editorType": "sql", + "format": 0, + "meta": { + "builderOptions": { + "aggregates": [ + { + "aggregateType": "count", + "column": "" + } + ], + "columns": [ + { + "hint": "time", + "name": "Timestamp", + "type": "DateTime64(9)" + } + ], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "hint": "time", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "ServiceName" + ], + "limit": 10000, + "mode": "trend", + "orderBy": [], + "queryType": "timeseries", + "table": "otel_traces" + } + }, + "pluginVersion": "4.0.6", + "queryType": "timeseries", + "rawSql": "SELECT\r\n $__timeInterval(Timestamp) as time,\r\n count(*) as ` `,\r\n ServiceName\r\nFROM otel.otel_traces\r\nWHERE\r\n $__conditionalAll(TraceId, $trace_id)\r\n AND ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )\r\n AND $__conditionalAll(ServiceName, $service_name)\r\n AND $__conditionalAll(SpanName, $span_name)\r\n AND (($ray_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['ray_id'], $ray_id)\r\n AND (($workflow_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['workflow_id'], $workflow_id))\r\n AND StatusCode IN ('Error', 'STATUS_CODE_ERROR')\r\n AND ServiceName != 'loadgenerator' GROUP BY ServiceName, time\r\nORDER BY time ASC\r\nLIMIT 100000", + "refId": "A" + } + ], + "title": "Error rates", + "type": "timeseries" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 49 + }, + "id": 10, + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 61 + }, + "id": 11, + "options": { + "dedupStrategy": "none", + "enableInfiniteScrolling": false, + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": true, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "builderOptions": { + "columns": [ + { + "hint": "time", + "name": "Timestamp", + "type": "DateTime64(9)" + }, + { + "hint": "log_level", + "name": "SeverityText", + "type": "LowCardinality(String)" + }, + { + "hint": "log_message", + "name": "Body", + "type": "String" + } + ], + "database": "otel", + "filters": [], + "limit": 1000, + "meta": { + "logMessageLike": "", + "otelVersion": "latest" + }, + "mode": "list", + "orderBy": [], + "queryType": "logs", + "table": "otel_logs" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorType": "builder", + "format": 2, + "pluginVersion": "4.0.6", + "rawSql": "SELECT Timestamp as timestamp, Body as body, SeverityText as level FROM \"otel\".\"otel_logs\" LIMIT 1000", + "refId": "A" + } + ], + "title": "Trace Logs", + "type": "logs" + } + ], + "title": "Logs", + "type": "row" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "ClickHouse", + "value": "ClickHouse" + }, + "includeAll": false, + "label": "ClickHouse instance", + "name": "datasource", + "options": [], + "query": "grafana-clickhouse-datasource", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ServiceName FROM otel.otel_traces", + "includeAll": true, + "label": "Service Name", + "multi": true, + "name": "service_name", + "options": [], + "query": "SELECT DISTINCT ServiceName FROM otel.otel_traces", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT TraceId FROM otel.otel_traces WHERE ParentSpanId = '' LIMIT 100", + "includeAll": true, + "label": "Trace ID", + "name": "trace_id", + "options": [], + "query": "SELECT DISTINCT TraceId FROM otel.otel_traces WHERE ParentSpanId = '' LIMIT 100", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT SpanName FROM otel.otel_traces WHERE $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "description": "", + "includeAll": true, + "label": "Span", + "multi": true, + "name": "span_name", + "options": [], + "query": "SELECT DISTINCT SpanName FROM otel.otel_traces WHERE $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "allValue": "'All'", + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT SpanAttributes['ray_id'] FROM otel.otel_traces WHERE SpanAttributes['ray_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "description": "", + "includeAll": true, + "label": "Ray ID", + "multi": true, + "name": "ray_id", + "options": [], + "query": "SELECT DISTINCT SpanAttributes['ray_id'] FROM otel.otel_traces WHERE SpanAttributes['ray_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "allValue": "'All'", + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT SpanAttributes['workflow_id'] FROM otel.otel_traces WHERE SpanAttributes['workflow_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "description": "", + "includeAll": true, + "label": "Workflow ID", + "multi": true, + "name": "workflow_id", + "options": [], + "query": "SELECT DISTINCT SpanAttributes['workflow_id'] FROM otel.otel_traces WHERE SpanAttributes['workflow_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "America/Los_Angeles", + "title": "Traces", + "uid": "8klBUGfVk", + "version": 2, + "weekStart": "" +} diff --git a/docker/dev-multidc/core/grafana/grafana.ini b/docker/dev-multidc/core/grafana/grafana.ini new file mode 100644 index 0000000000..1bd9bfe697 --- /dev/null +++ b/docker/dev-multidc/core/grafana/grafana.ini @@ -0,0 +1,14 @@ +[server] +http_port = 3000 +root_url = http://localhost:3100 + +[security] +admin_user = admin +admin_password = admin + +[auth.anonymous] +enabled = true +org_role = Viewer + +[dashboards] +default_home_dashboard_path = /var/lib/grafana/dashboards/api.json diff --git a/docker/dev-multidc/core/grafana/provisioning/dashboards/dashboards.yaml b/docker/dev-multidc/core/grafana/provisioning/dashboards/dashboards.yaml new file mode 100644 index 0000000000..7d91589dc7 --- /dev/null +++ b/docker/dev-multidc/core/grafana/provisioning/dashboards/dashboards.yaml @@ -0,0 +1,10 @@ +apiVersion: 1 +providers: + - name: rivet-dashboards + orgId: 1 + folder: '' + type: file + disableDeletion: false + updateIntervalSeconds: 10 + options: + path: /var/lib/grafana/dashboards diff --git a/docker/dev-multidc/core/grafana/provisioning/datasources/datasources.yaml b/docker/dev-multidc/core/grafana/provisioning/datasources/datasources.yaml new file mode 100644 index 0000000000..f66d3bf036 --- /dev/null +++ b/docker/dev-multidc/core/grafana/provisioning/datasources/datasources.yaml @@ -0,0 +1,30 @@ +apiVersion: 1 +datasources: + - name: ClickHouse + uid: clickhouse + type: grafana-clickhouse-datasource + access: proxy + secureJsonData: + password: default + jsonData: + version: 2.0.0 + host: clickhouse + port: 9300 + defaultDatabase: default + protocol: http + secure: false + username: default + validateSql: true + logs: + otelEnabled: true + otelVersion: 1.2.9 + defaultDatabase: otel + defaultTable: otel_logs + timeColumn: TimestampTime + messageColumn: Body + levelColumn: SeverityText + traces: + otelEnabled: true + otelVersion: 1.2.9 + defaultDatabase: otel + defaultTable: otel_traces diff --git a/docker/dev-multidc/datacenters/dc-a/otel-collector-client/config.yaml b/docker/dev-multidc/datacenters/dc-a/otel-collector-client/config.yaml new file mode 100644 index 0000000000..f3077ceb1c --- /dev/null +++ b/docker/dev-multidc/datacenters/dc-a/otel-collector-client/config.yaml @@ -0,0 +1,39 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + http: + endpoint: 0.0.0.0:4318 +processors: + batch: + timeout: 5s + send_batch_size: 10000 +exporters: + otlp/server: + endpoint: otel-collector-server-dc-a:4317 + tls: + insecure: true +service: + pipelines: + logs: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server + traces: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server + metrics: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server diff --git a/docker/dev-multidc/datacenters/dc-a/otel-collector-server/config.yaml b/docker/dev-multidc/datacenters/dc-a/otel-collector-server/config.yaml new file mode 100644 index 0000000000..a74179019e --- /dev/null +++ b/docker/dev-multidc/datacenters/dc-a/otel-collector-server/config.yaml @@ -0,0 +1,61 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 +processors: + batch: + timeout: 5s + send_batch_size: 10000 +exporters: + clickhouse: + endpoint: http://clickhouse:9300 + database: otel + username: default + password: ${env:CLICKHOUSE_PASSWORD} + async_insert: true + ttl: 72h + compress: lz4 + create_schema: true + logs_table_name: otel_logs + traces_table_name: otel_traces + timeout: 5s + metrics_tables: + gauge: + name: otel_metrics_gauge + sum: + name: otel_metrics_sum + summary: + name: otel_metrics_summary + histogram: + name: otel_metrics_histogram + exponential_histogram: + name: otel_metrics_exp_histogram + retry_on_failure: + enabled: true + initial_interval: 5s + max_interval: 30s + max_elapsed_time: 300s +service: + pipelines: + logs: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse + traces: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse + metrics: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse diff --git a/docker/dev-multidc/datacenters/dc-a/postgres/init-db.sh b/docker/dev-multidc/datacenters/dc-a/postgres/init-db.sh new file mode 100755 index 0000000000..6b57fcfef7 --- /dev/null +++ b/docker/dev-multidc/datacenters/dc-a/postgres/init-db.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -e + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + CREATE DATABASE rivet_engine; +EOSQL diff --git a/docker/dev-multidc/datacenters/dc-a/rivet-engine/config.jsonc b/docker/dev-multidc/datacenters/dc-a/rivet-engine/config.jsonc new file mode 100644 index 0000000000..f3f2264c0a --- /dev/null +++ b/docker/dev-multidc/datacenters/dc-a/rivet-engine/config.jsonc @@ -0,0 +1,70 @@ +{ + "guard": { + "port": 6420 + }, + "api_public": { + "lan_host": "rivet-engine-dc-a", + "host": "0.0.0.0", + "port": 6421 + }, + "api_peer": { + "host": "0.0.0.0", + "port": 6422 + }, + "pegboard": { + "lan_host": "rivet-engine-dc-a", + "host": "0.0.0.0", + "port": 6423 + }, + "logs": {}, + "topology": { + "datacenter_label": 1, + "datacenters": [ + { + "name": "dc-a", + "datacenter_label": 1, + "is_leader": true, + "api_peer_url": "http://rivet-engine-dc-a:6422", + "guard_url": "http://rivet-engine-dc-a:6420" + }, + { + "name": "dc-b", + "datacenter_label": 2, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-b:6422", + "guard_url": "http://rivet-engine-dc-b:6420" + }, + { + "name": "dc-c", + "datacenter_label": 3, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-c:6422", + "guard_url": "http://rivet-engine-dc-c:6420" + } + ] + }, + "postgres": { + "url": "postgresql://postgres:postgres@postgres-dc-a:5432/rivet_engine" + }, + "cache": { + "driver": "in_memory" + }, + "clickhouse": { + "http_url": "http://clickhouse:9300", + "native_url": "http://clickhouse:9301", + "username": "system", + "password": "default", + "provision_users": { + "vector": { + "username": "vector", + "password": "vector", + "role": "write" + } + }, + "secure": false + }, + "vector_http": { + "host": "vector-client-dc-a", + "port": 5022 + } +} \ No newline at end of file diff --git a/docker/dev-multidc/datacenters/dc-a/vector-client/vector.yaml b/docker/dev-multidc/datacenters/dc-a/vector-client/vector.yaml new file mode 100644 index 0000000000..f71830ca66 --- /dev/null +++ b/docker/dev-multidc/datacenters/dc-a/vector-client/vector.yaml @@ -0,0 +1,31 @@ +# Vector Client Configuration for Datacenter: dc-a +# This Vector instance runs on each server to collect local logs and forward them +# to the central Vector server aggregator. + +api: + enabled: true + address: 0.0.0.0:8686 +sources: + http_events: + type: http_server + address: 0.0.0.0:5022 + encoding: ndjson +transforms: {} +sinks: + vector_server: + type: vector + inputs: + - http_events + address: vector-server-dc-a:6000 + version: '2' + buffer: + type: disk + max_size: 2147483648 + when_full: block + console_debug: + type: console + inputs: + - http_events + encoding: + codec: json + \ No newline at end of file diff --git a/docker/dev-multidc/datacenters/dc-a/vector-server/vector.yaml b/docker/dev-multidc/datacenters/dc-a/vector-server/vector.yaml new file mode 100644 index 0000000000..5dfdbff2f5 --- /dev/null +++ b/docker/dev-multidc/datacenters/dc-a/vector-server/vector.yaml @@ -0,0 +1,61 @@ +# Vector Server (Aggregator) Configuration +# This Vector instance acts as an aggregator that collects logs and metrics from all Vector clients +# across different datacenters and forwards them to ClickHouse and other sinks. + +api: + enabled: true + address: 0.0.0.0:8686 +sources: + vector: + type: vector + address: 0.0.0.0:6000 + version: '2' + tcp_json: + type: socket + mode: tcp + address: 0.0.0.0:6100 + decoding: + codec: json + http_json: + type: http_server + address: 0.0.0.0:6200 + encoding: json + vector_metrics: + type: internal_metrics + vector_logs: + type: internal_logs +transforms: + clickhouse_dynamic_events_filter: + type: filter + inputs: + - vector + condition: + type: vrl + source: .source == "clickhouse" + clickhouse_dynamic_events_transform: + type: remap + inputs: + - clickhouse_dynamic_events_filter + source: "# Extract and store metadata\n__database = .database\n__table = .table\n__columns = .columns\n\n# Create a new object with just the columns data\n. = {\n\t\"__database\": __database,\n\t\"__table\": __table,\n\t# By default insert namespace column since most tables include this\n\t\"namespace\": \"rivet\"\n}\n\t\n# Merge in the column data that should be inserted\n. = merge!(., __columns)\n" +sinks: + clickhouse_dynamic_events: + type: clickhouse + inputs: + - clickhouse_dynamic_events_transform + endpoint: http://clickhouse:9300 + database: '{{ __database }}' + table: '{{ __table }}' + compression: gzip + auth: + strategy: basic + user: system + password: default + batch: + max_events: 1000 + timeout_secs: 10 + console_vector_logs: + type: console + inputs: + - vector_logs + encoding: + codec: json diff --git a/docker/dev-multidc/datacenters/dc-b/otel-collector-client/config.yaml b/docker/dev-multidc/datacenters/dc-b/otel-collector-client/config.yaml new file mode 100644 index 0000000000..a187be889a --- /dev/null +++ b/docker/dev-multidc/datacenters/dc-b/otel-collector-client/config.yaml @@ -0,0 +1,39 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + http: + endpoint: 0.0.0.0:4318 +processors: + batch: + timeout: 5s + send_batch_size: 10000 +exporters: + otlp/server: + endpoint: otel-collector-server-dc-b:4317 + tls: + insecure: true +service: + pipelines: + logs: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server + traces: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server + metrics: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server diff --git a/docker/dev-multidc/datacenters/dc-b/otel-collector-server/config.yaml b/docker/dev-multidc/datacenters/dc-b/otel-collector-server/config.yaml new file mode 100644 index 0000000000..a74179019e --- /dev/null +++ b/docker/dev-multidc/datacenters/dc-b/otel-collector-server/config.yaml @@ -0,0 +1,61 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 +processors: + batch: + timeout: 5s + send_batch_size: 10000 +exporters: + clickhouse: + endpoint: http://clickhouse:9300 + database: otel + username: default + password: ${env:CLICKHOUSE_PASSWORD} + async_insert: true + ttl: 72h + compress: lz4 + create_schema: true + logs_table_name: otel_logs + traces_table_name: otel_traces + timeout: 5s + metrics_tables: + gauge: + name: otel_metrics_gauge + sum: + name: otel_metrics_sum + summary: + name: otel_metrics_summary + histogram: + name: otel_metrics_histogram + exponential_histogram: + name: otel_metrics_exp_histogram + retry_on_failure: + enabled: true + initial_interval: 5s + max_interval: 30s + max_elapsed_time: 300s +service: + pipelines: + logs: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse + traces: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse + metrics: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse diff --git a/docker/dev-multidc/datacenters/dc-b/postgres/init-db.sh b/docker/dev-multidc/datacenters/dc-b/postgres/init-db.sh new file mode 100755 index 0000000000..6b57fcfef7 --- /dev/null +++ b/docker/dev-multidc/datacenters/dc-b/postgres/init-db.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -e + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + CREATE DATABASE rivet_engine; +EOSQL diff --git a/docker/dev-multidc/datacenters/dc-b/rivet-engine/config.jsonc b/docker/dev-multidc/datacenters/dc-b/rivet-engine/config.jsonc new file mode 100644 index 0000000000..d2365a8454 --- /dev/null +++ b/docker/dev-multidc/datacenters/dc-b/rivet-engine/config.jsonc @@ -0,0 +1,70 @@ +{ + "guard": { + "port": 6420 + }, + "api_public": { + "lan_host": "rivet-engine-dc-b", + "host": "0.0.0.0", + "port": 6421 + }, + "api_peer": { + "host": "0.0.0.0", + "port": 6422 + }, + "pegboard": { + "lan_host": "rivet-engine-dc-b", + "host": "0.0.0.0", + "port": 6423 + }, + "logs": {}, + "topology": { + "datacenter_label": 2, + "datacenters": [ + { + "name": "dc-a", + "datacenter_label": 1, + "is_leader": true, + "api_peer_url": "http://rivet-engine-dc-a:6422", + "guard_url": "http://rivet-engine-dc-a:6420" + }, + { + "name": "dc-b", + "datacenter_label": 2, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-b:6422", + "guard_url": "http://rivet-engine-dc-b:6420" + }, + { + "name": "dc-c", + "datacenter_label": 3, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-c:6422", + "guard_url": "http://rivet-engine-dc-c:6420" + } + ] + }, + "postgres": { + "url": "postgresql://postgres:postgres@postgres-dc-b:5432/rivet_engine" + }, + "cache": { + "driver": "in_memory" + }, + "clickhouse": { + "http_url": "http://clickhouse:9300", + "native_url": "http://clickhouse:9301", + "username": "system", + "password": "default", + "provision_users": { + "vector": { + "username": "vector", + "password": "vector", + "role": "write" + } + }, + "secure": false + }, + "vector_http": { + "host": "vector-client-dc-b", + "port": 5022 + } +} \ No newline at end of file diff --git a/docker/dev-multidc/datacenters/dc-b/vector-client/vector.yaml b/docker/dev-multidc/datacenters/dc-b/vector-client/vector.yaml new file mode 100644 index 0000000000..d1f0cda93c --- /dev/null +++ b/docker/dev-multidc/datacenters/dc-b/vector-client/vector.yaml @@ -0,0 +1,31 @@ +# Vector Client Configuration for Datacenter: dc-b +# This Vector instance runs on each server to collect local logs and forward them +# to the central Vector server aggregator. + +api: + enabled: true + address: 0.0.0.0:8686 +sources: + http_events: + type: http_server + address: 0.0.0.0:5022 + encoding: ndjson +transforms: {} +sinks: + vector_server: + type: vector + inputs: + - http_events + address: vector-server-dc-b:6000 + version: '2' + buffer: + type: disk + max_size: 2147483648 + when_full: block + console_debug: + type: console + inputs: + - http_events + encoding: + codec: json + \ No newline at end of file diff --git a/docker/dev-multidc/datacenters/dc-b/vector-server/vector.yaml b/docker/dev-multidc/datacenters/dc-b/vector-server/vector.yaml new file mode 100644 index 0000000000..5dfdbff2f5 --- /dev/null +++ b/docker/dev-multidc/datacenters/dc-b/vector-server/vector.yaml @@ -0,0 +1,61 @@ +# Vector Server (Aggregator) Configuration +# This Vector instance acts as an aggregator that collects logs and metrics from all Vector clients +# across different datacenters and forwards them to ClickHouse and other sinks. + +api: + enabled: true + address: 0.0.0.0:8686 +sources: + vector: + type: vector + address: 0.0.0.0:6000 + version: '2' + tcp_json: + type: socket + mode: tcp + address: 0.0.0.0:6100 + decoding: + codec: json + http_json: + type: http_server + address: 0.0.0.0:6200 + encoding: json + vector_metrics: + type: internal_metrics + vector_logs: + type: internal_logs +transforms: + clickhouse_dynamic_events_filter: + type: filter + inputs: + - vector + condition: + type: vrl + source: .source == "clickhouse" + clickhouse_dynamic_events_transform: + type: remap + inputs: + - clickhouse_dynamic_events_filter + source: "# Extract and store metadata\n__database = .database\n__table = .table\n__columns = .columns\n\n# Create a new object with just the columns data\n. = {\n\t\"__database\": __database,\n\t\"__table\": __table,\n\t# By default insert namespace column since most tables include this\n\t\"namespace\": \"rivet\"\n}\n\t\n# Merge in the column data that should be inserted\n. = merge!(., __columns)\n" +sinks: + clickhouse_dynamic_events: + type: clickhouse + inputs: + - clickhouse_dynamic_events_transform + endpoint: http://clickhouse:9300 + database: '{{ __database }}' + table: '{{ __table }}' + compression: gzip + auth: + strategy: basic + user: system + password: default + batch: + max_events: 1000 + timeout_secs: 10 + console_vector_logs: + type: console + inputs: + - vector_logs + encoding: + codec: json diff --git a/docker/dev-multidc/datacenters/dc-c/otel-collector-client/config.yaml b/docker/dev-multidc/datacenters/dc-c/otel-collector-client/config.yaml new file mode 100644 index 0000000000..ca6a47e900 --- /dev/null +++ b/docker/dev-multidc/datacenters/dc-c/otel-collector-client/config.yaml @@ -0,0 +1,39 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + http: + endpoint: 0.0.0.0:4318 +processors: + batch: + timeout: 5s + send_batch_size: 10000 +exporters: + otlp/server: + endpoint: otel-collector-server-dc-c:4317 + tls: + insecure: true +service: + pipelines: + logs: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server + traces: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server + metrics: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server diff --git a/docker/dev-multidc/datacenters/dc-c/otel-collector-server/config.yaml b/docker/dev-multidc/datacenters/dc-c/otel-collector-server/config.yaml new file mode 100644 index 0000000000..a74179019e --- /dev/null +++ b/docker/dev-multidc/datacenters/dc-c/otel-collector-server/config.yaml @@ -0,0 +1,61 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 +processors: + batch: + timeout: 5s + send_batch_size: 10000 +exporters: + clickhouse: + endpoint: http://clickhouse:9300 + database: otel + username: default + password: ${env:CLICKHOUSE_PASSWORD} + async_insert: true + ttl: 72h + compress: lz4 + create_schema: true + logs_table_name: otel_logs + traces_table_name: otel_traces + timeout: 5s + metrics_tables: + gauge: + name: otel_metrics_gauge + sum: + name: otel_metrics_sum + summary: + name: otel_metrics_summary + histogram: + name: otel_metrics_histogram + exponential_histogram: + name: otel_metrics_exp_histogram + retry_on_failure: + enabled: true + initial_interval: 5s + max_interval: 30s + max_elapsed_time: 300s +service: + pipelines: + logs: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse + traces: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse + metrics: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse diff --git a/docker/dev-multidc/datacenters/dc-c/postgres/init-db.sh b/docker/dev-multidc/datacenters/dc-c/postgres/init-db.sh new file mode 100755 index 0000000000..6b57fcfef7 --- /dev/null +++ b/docker/dev-multidc/datacenters/dc-c/postgres/init-db.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -e + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + CREATE DATABASE rivet_engine; +EOSQL diff --git a/docker/dev-multidc/datacenters/dc-c/rivet-engine/config.jsonc b/docker/dev-multidc/datacenters/dc-c/rivet-engine/config.jsonc new file mode 100644 index 0000000000..c936e0e0f0 --- /dev/null +++ b/docker/dev-multidc/datacenters/dc-c/rivet-engine/config.jsonc @@ -0,0 +1,70 @@ +{ + "guard": { + "port": 6420 + }, + "api_public": { + "lan_host": "rivet-engine-dc-c", + "host": "0.0.0.0", + "port": 6421 + }, + "api_peer": { + "host": "0.0.0.0", + "port": 6422 + }, + "pegboard": { + "lan_host": "rivet-engine-dc-c", + "host": "0.0.0.0", + "port": 6423 + }, + "logs": {}, + "topology": { + "datacenter_label": 3, + "datacenters": [ + { + "name": "dc-a", + "datacenter_label": 1, + "is_leader": true, + "api_peer_url": "http://rivet-engine-dc-a:6422", + "guard_url": "http://rivet-engine-dc-a:6420" + }, + { + "name": "dc-b", + "datacenter_label": 2, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-b:6422", + "guard_url": "http://rivet-engine-dc-b:6420" + }, + { + "name": "dc-c", + "datacenter_label": 3, + "is_leader": false, + "api_peer_url": "http://rivet-engine-dc-c:6422", + "guard_url": "http://rivet-engine-dc-c:6420" + } + ] + }, + "postgres": { + "url": "postgresql://postgres:postgres@postgres-dc-c:5432/rivet_engine" + }, + "cache": { + "driver": "in_memory" + }, + "clickhouse": { + "http_url": "http://clickhouse:9300", + "native_url": "http://clickhouse:9301", + "username": "system", + "password": "default", + "provision_users": { + "vector": { + "username": "vector", + "password": "vector", + "role": "write" + } + }, + "secure": false + }, + "vector_http": { + "host": "vector-client-dc-c", + "port": 5022 + } +} \ No newline at end of file diff --git a/docker/dev-multidc/datacenters/dc-c/vector-client/vector.yaml b/docker/dev-multidc/datacenters/dc-c/vector-client/vector.yaml new file mode 100644 index 0000000000..717ddb2133 --- /dev/null +++ b/docker/dev-multidc/datacenters/dc-c/vector-client/vector.yaml @@ -0,0 +1,31 @@ +# Vector Client Configuration for Datacenter: dc-c +# This Vector instance runs on each server to collect local logs and forward them +# to the central Vector server aggregator. + +api: + enabled: true + address: 0.0.0.0:8686 +sources: + http_events: + type: http_server + address: 0.0.0.0:5022 + encoding: ndjson +transforms: {} +sinks: + vector_server: + type: vector + inputs: + - http_events + address: vector-server-dc-c:6000 + version: '2' + buffer: + type: disk + max_size: 2147483648 + when_full: block + console_debug: + type: console + inputs: + - http_events + encoding: + codec: json + \ No newline at end of file diff --git a/docker/dev-multidc/datacenters/dc-c/vector-server/vector.yaml b/docker/dev-multidc/datacenters/dc-c/vector-server/vector.yaml new file mode 100644 index 0000000000..5dfdbff2f5 --- /dev/null +++ b/docker/dev-multidc/datacenters/dc-c/vector-server/vector.yaml @@ -0,0 +1,61 @@ +# Vector Server (Aggregator) Configuration +# This Vector instance acts as an aggregator that collects logs and metrics from all Vector clients +# across different datacenters and forwards them to ClickHouse and other sinks. + +api: + enabled: true + address: 0.0.0.0:8686 +sources: + vector: + type: vector + address: 0.0.0.0:6000 + version: '2' + tcp_json: + type: socket + mode: tcp + address: 0.0.0.0:6100 + decoding: + codec: json + http_json: + type: http_server + address: 0.0.0.0:6200 + encoding: json + vector_metrics: + type: internal_metrics + vector_logs: + type: internal_logs +transforms: + clickhouse_dynamic_events_filter: + type: filter + inputs: + - vector + condition: + type: vrl + source: .source == "clickhouse" + clickhouse_dynamic_events_transform: + type: remap + inputs: + - clickhouse_dynamic_events_filter + source: "# Extract and store metadata\n__database = .database\n__table = .table\n__columns = .columns\n\n# Create a new object with just the columns data\n. = {\n\t\"__database\": __database,\n\t\"__table\": __table,\n\t# By default insert namespace column since most tables include this\n\t\"namespace\": \"rivet\"\n}\n\t\n# Merge in the column data that should be inserted\n. = merge!(., __columns)\n" +sinks: + clickhouse_dynamic_events: + type: clickhouse + inputs: + - clickhouse_dynamic_events_transform + endpoint: http://clickhouse:9300 + database: '{{ __database }}' + table: '{{ __table }}' + compression: gzip + auth: + strategy: basic + user: system + password: default + batch: + max_events: 1000 + timeout_secs: 10 + console_vector_logs: + type: console + inputs: + - vector_logs + encoding: + codec: json diff --git a/docker/dev-multidc/docker-compose.yml b/docker/dev-multidc/docker-compose.yml new file mode 100644 index 0000000000..00182d067e --- /dev/null +++ b/docker/dev-multidc/docker-compose.yml @@ -0,0 +1,531 @@ +services: + clickhouse: + restart: unless-stopped + image: clickhouse/clickhouse-server:25.1.5 + volumes: + - clickhouse-data:/var/lib/clickhouse + - ./core/clickhouse/config.xml:/etc/clickhouse-server/config.d/config.xml + - ./core/clickhouse/users.xml:/etc/clickhouse-server/users.d/users.xml + - ./core/clickhouse/client-config.xml:/etc/clickhouse-client/config.xml + - ./core/clickhouse/init:/docker-entrypoint-initdb.d + environment: + - CLICKHOUSE_ALWAYS_RUN_INITDB_SCRIPTS=true + - CLICKHOUSE_USER=default + - CLICKHOUSE_PASSWORD=default + - CLICKHOUSE_HTTP_PORT=9300 + - CLICKHOUSE_TCP_PORT=9301 + networks: + - rivet-network-dc-a-to-core + - rivet-network-dc-b-to-core + - rivet-network-dc-c-to-core + - rivet-core-network + healthcheck: + test: + - CMD + - clickhouse-client + - '--host' + - 127.0.0.1 + - '--port' + - '9301' + - '--user' + - system + - '--password' + - default + - '--query' + - SELECT 1 + interval: 2s + timeout: 10s + retries: 10 + grafana: + image: grafana/grafana:11.5.2 + volumes: + - grafana-data:/var/lib/grafana + - ./core/grafana/grafana.ini:/etc/grafana/grafana.ini + - ./core/grafana/provisioning:/etc/grafana/provisioning + - ./core/grafana/dashboards:/var/lib/grafana/dashboards + environment: + - GF_INSTALL_PLUGINS=grafana-clickhouse-datasource + ports: + - '3100:3000' + networks: + - rivet-core-network + depends_on: + clickhouse: + condition: service_healthy + postgres-dc-a: + restart: unless-stopped + image: postgres:16-alpine + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=postgres + volumes: + - >- + ./datacenters/dc-a/postgres/init-db.sh:/docker-entrypoint-initdb.d/init-db.sh + - postgres-data-dc-a:/var/lib/postgresql/data + ports: + - '5432:5432' + healthcheck: + test: + - CMD-SHELL + - pg_isready -U postgres -d postgres + interval: 2s + timeout: 10s + retries: 10 + networks: + - rivet-network-dc-a + rivet-shell-dc-a: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: sleep infinity + stop_grace_period: 0s + depends_on: + postgres-dc-a: + condition: service_healthy + volumes: + - ./datacenters/dc-a/rivet-engine/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network-dc-a + - rivet-network-dc-a-to-core + - rivet-network-dc-a-engine-peer + - rivet-network-dc-b-engine-peer + - rivet-network-dc-c-engine-peer + vector-server-dc-a: + restart: unless-stopped + image: timberio/vector:0.48.0-distroless-static + command: '-C /etc/vector' + volumes: + - vector-server-data-dc-a:/var/lib/vector + - ./datacenters/dc-a/vector-server:/etc/vector + networks: + - rivet-network-dc-a + - rivet-network-dc-a-to-core + depends_on: + clickhouse: + condition: service_healthy + vector-client-dc-a: + restart: unless-stopped + image: timberio/vector:0.48.0-distroless-static + command: '-C /etc/vector' + volumes: + - vector-client-data-dc-a:/var/lib/vector + - ./datacenters/dc-a/vector-client:/etc/vector + networks: + - rivet-network-dc-a + depends_on: + vector-server-dc-a: + condition: service_started + otel-collector-server-dc-a: + image: otel/opentelemetry-collector-contrib:latest + restart: unless-stopped + command: '--config=/etc/otel/config.yaml' + volumes: + - >- + ./datacenters/dc-a/otel-collector-server/config.yaml:/etc/otel/config.yaml:ro + environment: + - CLICKHOUSE_PASSWORD=default + depends_on: + clickhouse: + condition: service_healthy + networks: + - rivet-network-dc-a + - rivet-network-dc-a-to-core + otel-collector-client-dc-a: + image: otel/opentelemetry-collector-contrib:latest + restart: unless-stopped + command: '--config=/etc/otel/config.yaml' + volumes: + - >- + ./datacenters/dc-a/otel-collector-client/config.yaml:/etc/otel/config.yaml:ro + depends_on: + otel-collector-server-dc-a: + condition: service_started + networks: + - rivet-network-dc-a + rivet-engine-dc-a: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: /usr/bin/rivet-engine start + environment: + - RUST_LOG_ANSI_COLOR=1 + - RIVET_OTEL_ENABLED=1 + - RIVET_OTEL_SAMPLER_RATIO=1 + - RIVET_OTEL_GRPC_ENDPOINT=http://otel-collector-client-dc-a:4317 + stop_grace_period: 0s + depends_on: + vector-client-dc-a: + condition: service_started + otel-collector-client-dc-a: + condition: service_started + postgres-dc-a: + condition: service_healthy + volumes: + - ./datacenters/dc-a/rivet-engine/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network-dc-a + - rivet-network-dc-a-to-core + - rivet-network-dc-a-engine-peer + - rivet-network-dc-b-engine-peer + - rivet-network-dc-c-engine-peer + ports: + - '6420:6420' + healthcheck: + test: + - CMD + - curl + - '-f' + - http://127.0.0.1:6421/health + interval: 2s + timeout: 10s + retries: 10 + start_period: 30s + runner-dc-a: + build: + context: ../.. + dockerfile: sdks/typescript/test-runner/Dockerfile + platform: linux/amd64 + restart: unless-stopped + environment: + - RIVET_ENDPOINT=http://rivet-engine-dc-a:6420 + - RUNNER_HOST=runner-dc-a + stop_grace_period: 4s + ports: + - '5050:5050' + depends_on: + rivet-engine-dc-a: + condition: service_healthy + networks: + - rivet-network-dc-a + postgres-dc-b: + restart: unless-stopped + image: postgres:16-alpine + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=postgres + volumes: + - >- + ./datacenters/dc-b/postgres/init-db.sh:/docker-entrypoint-initdb.d/init-db.sh + - postgres-data-dc-b:/var/lib/postgresql/data + healthcheck: + test: + - CMD-SHELL + - pg_isready -U postgres -d postgres + interval: 2s + timeout: 10s + retries: 10 + networks: + - rivet-network-dc-b + rivet-shell-dc-b: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: sleep infinity + stop_grace_period: 0s + depends_on: + postgres-dc-b: + condition: service_healthy + volumes: + - ./datacenters/dc-b/rivet-engine/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network-dc-b + - rivet-network-dc-b-to-core + - rivet-network-dc-a-engine-peer + - rivet-network-dc-b-engine-peer + - rivet-network-dc-c-engine-peer + vector-server-dc-b: + restart: unless-stopped + image: timberio/vector:0.48.0-distroless-static + command: '-C /etc/vector' + volumes: + - vector-server-data-dc-b:/var/lib/vector + - ./datacenters/dc-b/vector-server:/etc/vector + networks: + - rivet-network-dc-b + - rivet-network-dc-b-to-core + depends_on: + clickhouse: + condition: service_healthy + vector-client-dc-b: + restart: unless-stopped + image: timberio/vector:0.48.0-distroless-static + command: '-C /etc/vector' + volumes: + - vector-client-data-dc-b:/var/lib/vector + - ./datacenters/dc-b/vector-client:/etc/vector + networks: + - rivet-network-dc-b + depends_on: + vector-server-dc-b: + condition: service_started + otel-collector-server-dc-b: + image: otel/opentelemetry-collector-contrib:latest + restart: unless-stopped + command: '--config=/etc/otel/config.yaml' + volumes: + - >- + ./datacenters/dc-b/otel-collector-server/config.yaml:/etc/otel/config.yaml:ro + environment: + - CLICKHOUSE_PASSWORD=default + depends_on: + clickhouse: + condition: service_healthy + networks: + - rivet-network-dc-b + - rivet-network-dc-b-to-core + otel-collector-client-dc-b: + image: otel/opentelemetry-collector-contrib:latest + restart: unless-stopped + command: '--config=/etc/otel/config.yaml' + volumes: + - >- + ./datacenters/dc-b/otel-collector-client/config.yaml:/etc/otel/config.yaml:ro + depends_on: + otel-collector-server-dc-b: + condition: service_started + networks: + - rivet-network-dc-b + rivet-engine-dc-b: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: /usr/bin/rivet-engine start + environment: + - RUST_LOG_ANSI_COLOR=1 + - RIVET_OTEL_ENABLED=1 + - RIVET_OTEL_SAMPLER_RATIO=1 + - RIVET_OTEL_GRPC_ENDPOINT=http://otel-collector-client-dc-b:4317 + stop_grace_period: 0s + depends_on: + vector-client-dc-b: + condition: service_started + otel-collector-client-dc-b: + condition: service_started + postgres-dc-b: + condition: service_healthy + volumes: + - ./datacenters/dc-b/rivet-engine/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network-dc-b + - rivet-network-dc-b-to-core + - rivet-network-dc-a-engine-peer + - rivet-network-dc-b-engine-peer + - rivet-network-dc-c-engine-peer + healthcheck: + test: + - CMD + - curl + - '-f' + - http://127.0.0.1:6421/health + interval: 2s + timeout: 10s + retries: 10 + start_period: 30s + runner-dc-b: + build: + context: ../.. + dockerfile: sdks/typescript/test-runner/Dockerfile + platform: linux/amd64 + restart: unless-stopped + environment: + - RIVET_ENDPOINT=http://rivet-engine-dc-b:6420 + - RUNNER_HOST=runner-dc-b + stop_grace_period: 4s + depends_on: + rivet-engine-dc-b: + condition: service_healthy + networks: + - rivet-network-dc-b + postgres-dc-c: + restart: unless-stopped + image: postgres:16-alpine + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=postgres + volumes: + - >- + ./datacenters/dc-c/postgres/init-db.sh:/docker-entrypoint-initdb.d/init-db.sh + - postgres-data-dc-c:/var/lib/postgresql/data + healthcheck: + test: + - CMD-SHELL + - pg_isready -U postgres -d postgres + interval: 2s + timeout: 10s + retries: 10 + networks: + - rivet-network-dc-c + rivet-shell-dc-c: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: sleep infinity + stop_grace_period: 0s + depends_on: + postgres-dc-c: + condition: service_healthy + volumes: + - ./datacenters/dc-c/rivet-engine/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network-dc-c + - rivet-network-dc-c-to-core + - rivet-network-dc-a-engine-peer + - rivet-network-dc-b-engine-peer + - rivet-network-dc-c-engine-peer + vector-server-dc-c: + restart: unless-stopped + image: timberio/vector:0.48.0-distroless-static + command: '-C /etc/vector' + volumes: + - vector-server-data-dc-c:/var/lib/vector + - ./datacenters/dc-c/vector-server:/etc/vector + networks: + - rivet-network-dc-c + - rivet-network-dc-c-to-core + depends_on: + clickhouse: + condition: service_healthy + vector-client-dc-c: + restart: unless-stopped + image: timberio/vector:0.48.0-distroless-static + command: '-C /etc/vector' + volumes: + - vector-client-data-dc-c:/var/lib/vector + - ./datacenters/dc-c/vector-client:/etc/vector + networks: + - rivet-network-dc-c + depends_on: + vector-server-dc-c: + condition: service_started + otel-collector-server-dc-c: + image: otel/opentelemetry-collector-contrib:latest + restart: unless-stopped + command: '--config=/etc/otel/config.yaml' + volumes: + - >- + ./datacenters/dc-c/otel-collector-server/config.yaml:/etc/otel/config.yaml:ro + environment: + - CLICKHOUSE_PASSWORD=default + depends_on: + clickhouse: + condition: service_healthy + networks: + - rivet-network-dc-c + - rivet-network-dc-c-to-core + otel-collector-client-dc-c: + image: otel/opentelemetry-collector-contrib:latest + restart: unless-stopped + command: '--config=/etc/otel/config.yaml' + volumes: + - >- + ./datacenters/dc-c/otel-collector-client/config.yaml:/etc/otel/config.yaml:ro + depends_on: + otel-collector-server-dc-c: + condition: service_started + networks: + - rivet-network-dc-c + rivet-engine-dc-c: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: /usr/bin/rivet-engine start + environment: + - RUST_LOG_ANSI_COLOR=1 + - RIVET_OTEL_ENABLED=1 + - RIVET_OTEL_SAMPLER_RATIO=1 + - RIVET_OTEL_GRPC_ENDPOINT=http://otel-collector-client-dc-c:4317 + stop_grace_period: 0s + depends_on: + vector-client-dc-c: + condition: service_started + otel-collector-client-dc-c: + condition: service_started + postgres-dc-c: + condition: service_healthy + volumes: + - ./datacenters/dc-c/rivet-engine/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network-dc-c + - rivet-network-dc-c-to-core + - rivet-network-dc-a-engine-peer + - rivet-network-dc-b-engine-peer + - rivet-network-dc-c-engine-peer + healthcheck: + test: + - CMD + - curl + - '-f' + - http://127.0.0.1:6421/health + interval: 2s + timeout: 10s + retries: 10 + start_period: 30s + runner-dc-c: + build: + context: ../.. + dockerfile: sdks/typescript/test-runner/Dockerfile + platform: linux/amd64 + restart: unless-stopped + environment: + - RIVET_ENDPOINT=http://rivet-engine-dc-c:6420 + - RUNNER_HOST=runner-dc-c + stop_grace_period: 4s + depends_on: + rivet-engine-dc-c: + condition: service_healthy + networks: + - rivet-network-dc-c +networks: + rivet-core-network: + driver: bridge + rivet-network-dc-a: + driver: bridge + rivet-network-dc-a-engine-peer: + driver: bridge + rivet-network-dc-a-to-core: + driver: bridge + rivet-network-dc-b: + driver: bridge + rivet-network-dc-b-engine-peer: + driver: bridge + rivet-network-dc-b-to-core: + driver: bridge + rivet-network-dc-c: + driver: bridge + rivet-network-dc-c-engine-peer: + driver: bridge + rivet-network-dc-c-to-core: + driver: bridge +volumes: + clickhouse-data: null + grafana-data: null + postgres-data-dc-a: null + vector-server-data-dc-a: null + vector-client-data-dc-a: null + postgres-data-dc-b: null + vector-server-data-dc-b: null + vector-client-data-dc-b: null + postgres-data-dc-c: null + vector-server-data-dc-c: null + vector-client-data-dc-c: null diff --git a/docker/dev-multinode/.gitattributes b/docker/dev-multinode/.gitattributes new file mode 100644 index 0000000000..447edeb5c2 --- /dev/null +++ b/docker/dev-multinode/.gitattributes @@ -0,0 +1 @@ +. linguist-generated=true diff --git a/docker/dev-multinode/README.md b/docker/dev-multinode/README.md new file mode 100644 index 0000000000..708c9e9615 --- /dev/null +++ b/docker/dev-multinode/README.md @@ -0,0 +1,74 @@ +# dev-multinode - Auto-generated Docker Compose Template + +> ! **Auto-generated**: This directory and its contents are automatically generated by `docker/template/`. Do not edit these files directly as your changes will be overwritten. + +## Overview + +This Docker Compose configuration provides a complete development environment for Rivet with the following services: + +- **Rivet Engine**: Main orchestration service +- **Rivet Shell**: Interactive shell for debugging +- **Runner**: Executes user code +- **ClickHouse**: Analytics and time-series database +- **PostgreSQL**: Relational database +- **Vector Server**: Log aggregation and processing +- **OpenTelemetry Collector**: Observability data collection + +## Port Configuration + +| Service | Port(s) | Description | +|---------|---------|-------------| +| Rivet Engine | 6420 | Public endpoint | +| Runner | 5050 | Code execution service | +| PostgreSQL | 5432 | Database | +| ClickHouse HTTP | 9300 | Database HTTP interface | +| ClickHouse Native | 9301 | Database native protocol | +| OpenTelemetry gRPC | 4317 | OTLP gRPC endpoint | +| OpenTelemetry HTTP | 4318 | OTLP HTTP endpoint | + +## Template Configuration + +**Template Name**: `dev-multinode` +**Base Port**: `6420` +**Network Mode**: `bridge` + +### Datacenters +- **1**: 3 engine(s), 3 runner(s) + +## Usage + +1. Start all services: + ```bash + docker-compose up -d + ``` + +2. Check service health: + ```bash + docker-compose ps + ``` + +3. View logs: + ```bash + docker-compose logs -f [service-name] + ``` + +4. Stop all services: + ```bash + docker-compose down + ``` + +## Generated Files + +This template generates the following files and directories: +- `docker-compose.yml` - Main Docker Compose configuration +- `core/` - Core services shared across datacenters: + - `clickhouse/` - ClickHouse configuration and initialization + - `vector-server/` - Vector aggregator configuration + - `otel-collector-server/` - OpenTelemetry Collector server configuration +- `datacenters/` - Datacenter-specific configurations: + - `1/` - Configuration for datacenter 1: + - `postgres/` - PostgreSQL setup scripts + - `rivet-engine/` - Rivet Engine configuration + - `vector-client/` - Vector client configuration + - `otel-collector-client/` - OpenTelemetry Collector client configuration +- `README.md` - This file diff --git a/docker/dev-multinode/clickhouse/client-config.xml b/docker/dev-multinode/clickhouse/client-config.xml new file mode 100644 index 0000000000..72f9850f4e --- /dev/null +++ b/docker/dev-multinode/clickhouse/client-config.xml @@ -0,0 +1,5 @@ + + + 9301 + 127.0.0.1 + \ No newline at end of file diff --git a/docker/dev-multinode/clickhouse/config.xml b/docker/dev-multinode/clickhouse/config.xml new file mode 100644 index 0000000000..e7ccd0480b --- /dev/null +++ b/docker/dev-multinode/clickhouse/config.xml @@ -0,0 +1,52 @@ + + + + debug + /var/log/clickhouse-server/clickhouse-server.log + /var/log/clickhouse-server/clickhouse-server.err.log + 1000M + 10 + + + :: + 9300 + 9301 + + + 9440 + 9010 + + 9009 + + 4096 + 3 + 100 + 8589934592 + 5368709120 + + /var/lib/clickhouse/ + /var/lib/clickhouse/tmp/ + /var/lib/clickhouse/user_files/ + /var/lib/clickhouse/access/ + + users.xml + default + default + UTC + + + + + + 3600 + 3600 + 60 + + + system + query_log
+ 7500 +
+ + *_dictionary.xml +
diff --git a/docker/dev-multinode/clickhouse/init/01-create-otel-table.sql b/docker/dev-multinode/clickhouse/init/01-create-otel-table.sql new file mode 100644 index 0000000000..2c7b9f7957 --- /dev/null +++ b/docker/dev-multinode/clickhouse/init/01-create-otel-table.sql @@ -0,0 +1,107 @@ +CREATE DATABASE IF NOT EXISTS otel; + +CREATE TABLE IF NOT EXISTS otel.otel_logs ( + Timestamp DateTime64(9) CODEC(Delta, ZSTD(1)), + ObservedTimestamp DateTime64(9) CODEC(Delta, ZSTD(1)), + TraceId String CODEC(ZSTD(1)), + SpanId String CODEC(ZSTD(1)), + TraceFlags UInt32 CODEC(ZSTD(1)), + SeverityText LowCardinality(String) CODEC(ZSTD(1)), + SeverityNumber Int32 CODEC(ZSTD(1)), + ServiceName LowCardinality(String) CODEC(ZSTD(1)), + Body String CODEC(ZSTD(1)), + ResourceSchemaUrl String CODEC(ZSTD(1)), + ResourceAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ScopeSchemaUrl String CODEC(ZSTD(1)), + ScopeName String CODEC(ZSTD(1)), + ScopeVersion String CODEC(ZSTD(1)), + ScopeAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + LogAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + INDEX idx_trace_id TraceId TYPE bloom_filter(0.001) GRANULARITY 1, + INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_key mapKeys(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_value mapValues(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_log_attr_key mapKeys(LogAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_log_attr_value mapValues(LogAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_body Body TYPE tokenbf_v1(32768, 3, 0) GRANULARITY 1 +) ENGINE = MergeTree() +PARTITION BY toDate(Timestamp) +ORDER BY (ServiceName, SeverityText, toUnixTimestamp(Timestamp), TraceId) +TTL toDateTime(Timestamp) + toIntervalDay(3) +SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1; + +CREATE TABLE IF NOT EXISTS otel.otel_traces ( + Timestamp DateTime64(9) CODEC(Delta, ZSTD(1)), + TraceId String CODEC(ZSTD(1)), + SpanId String CODEC(ZSTD(1)), + ParentSpanId String CODEC(ZSTD(1)), + TraceState String CODEC(ZSTD(1)), + SpanName LowCardinality(String) CODEC(ZSTD(1)), + SpanKind LowCardinality(String) CODEC(ZSTD(1)), + ServiceName LowCardinality(String) CODEC(ZSTD(1)), + ResourceAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ScopeName String CODEC(ZSTD(1)), + ScopeVersion String CODEC(ZSTD(1)), + SpanAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + Duration Int64 CODEC(ZSTD(1)), + StatusCode LowCardinality(String) CODEC(ZSTD(1)), + StatusMessage String CODEC(ZSTD(1)), + Events Nested ( + Timestamp DateTime64(9), + Name LowCardinality(String), + Attributes Map(LowCardinality(String), String) + ) CODEC(ZSTD(1)), + Links Nested ( + TraceId String, + SpanId String, + TraceState String, + Attributes Map(LowCardinality(String), String) + ) CODEC(ZSTD(1)), + INDEX idx_trace_id TraceId TYPE bloom_filter(0.001) GRANULARITY 1, + INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_span_attr_key mapKeys(SpanAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_span_attr_value mapValues(SpanAttributes) TYPE bloom_filter(0.01) GRANULARITY 1 +) ENGINE = MergeTree() +PARTITION BY toDate(Timestamp) +ORDER BY (ServiceName, SpanName, toUnixTimestamp(Timestamp), TraceId) +TTL toDateTime(Timestamp) + toIntervalDay(7) +SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1; + +CREATE TABLE IF NOT EXISTS otel.otel_metrics ( + ResourceAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ResourceSchemaUrl String CODEC(ZSTD(1)), + ScopeName String CODEC(ZSTD(1)), + ScopeVersion String CODEC(ZSTD(1)), + ScopeAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ScopeDroppedAttrCount UInt32 CODEC(ZSTD(1)), + ScopeSchemaUrl String CODEC(ZSTD(1)), + MetricName String CODEC(ZSTD(1)), + MetricDescription String CODEC(ZSTD(1)), + MetricUnit String CODEC(ZSTD(1)), + Attributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + StartTimeUnix DateTime64(9) CODEC(Delta, ZSTD(1)), + TimeUnix DateTime64(9) CODEC(Delta, ZSTD(1)), + Value Float64 CODEC(ZSTD(1)), + Flags UInt32 CODEC(ZSTD(1)), + Exemplars Nested ( + FilteredAttributes Map(LowCardinality(String), String), + TimeUnix DateTime64(9), + Value Float64, + SpanId String, + TraceId String + ) CODEC(ZSTD(1)), + AggTemp Int32 CODEC(ZSTD(1)), + IsMonotonic Bool CODEC(ZSTD(1)), + INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_key mapKeys(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_value mapValues(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_attr_key mapKeys(Attributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_attr_value mapValues(Attributes) TYPE bloom_filter(0.01) GRANULARITY 1 +) ENGINE = MergeTree() +PARTITION BY toDate(TimeUnix) +ORDER BY (MetricName, Attributes, toUnixTimestamp(TimeUnix)) +TTL toDateTime(TimeUnix) + toIntervalDay(30) +SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1; diff --git a/docker/dev-multinode/clickhouse/users.xml b/docker/dev-multinode/clickhouse/users.xml new file mode 100644 index 0000000000..743cada261 --- /dev/null +++ b/docker/dev-multinode/clickhouse/users.xml @@ -0,0 +1,35 @@ + + + + + default + + ::/0 + + default + default + 1 + + + + + + 10000000000 + 0 + random + + + + + + + 3600 + 0 + 0 + 0 + 0 + 0 + + + + diff --git a/docker/dev-multinode/docker-compose.yml b/docker/dev-multinode/docker-compose.yml new file mode 100644 index 0000000000..ad1d9a5eb7 --- /dev/null +++ b/docker/dev-multinode/docker-compose.yml @@ -0,0 +1,316 @@ +services: + clickhouse: + restart: unless-stopped + image: clickhouse/clickhouse-server:25.1.5 + volumes: + - clickhouse-data:/var/lib/clickhouse + - ./clickhouse/config.xml:/etc/clickhouse-server/config.d/config.xml + - ./clickhouse/users.xml:/etc/clickhouse-server/users.d/users.xml + - ./clickhouse/client-config.xml:/etc/clickhouse-client/config.xml + - ./clickhouse/init:/docker-entrypoint-initdb.d + environment: + - CLICKHOUSE_ALWAYS_RUN_INITDB_SCRIPTS=true + - CLICKHOUSE_USER=default + - CLICKHOUSE_PASSWORD=default + - CLICKHOUSE_HTTP_PORT=9300 + - CLICKHOUSE_TCP_PORT=9301 + networks: + - rivet-network-to-core + - rivet-core-network + healthcheck: + test: + - CMD + - clickhouse-client + - '--host' + - 127.0.0.1 + - '--port' + - '9301' + - '--user' + - system + - '--password' + - default + - '--query' + - SELECT 1 + interval: 2s + timeout: 10s + retries: 10 + grafana: + image: grafana/grafana:11.5.2 + volumes: + - grafana-data:/var/lib/grafana + - ./grafana/grafana.ini:/etc/grafana/grafana.ini + - ./grafana/provisioning:/etc/grafana/provisioning + - ./grafana/dashboards:/var/lib/grafana/dashboards + environment: + - GF_INSTALL_PLUGINS=grafana-clickhouse-datasource + ports: + - '3100:3000' + networks: + - rivet-core-network + depends_on: + clickhouse: + condition: service_healthy + postgres: + restart: unless-stopped + image: postgres:16-alpine + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=postgres + volumes: + - ./postgres/init-db.sh:/docker-entrypoint-initdb.d/init-db.sh + - postgres-data:/var/lib/postgresql/data + ports: + - '5432:5432' + healthcheck: + test: + - CMD-SHELL + - pg_isready -U postgres -d postgres + interval: 2s + timeout: 10s + retries: 10 + networks: + - rivet-network + rivet-shell: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: sleep infinity + stop_grace_period: 0s + depends_on: + postgres: + condition: service_healthy + volumes: + - ./rivet-engine/0/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network + - rivet-network-to-core + - rivet-network-engine-peer + vector-server: + restart: unless-stopped + image: timberio/vector:0.48.0-distroless-static + command: '-C /etc/vector' + volumes: + - vector-server-data-local:/var/lib/vector + - ./vector-server:/etc/vector + networks: + - rivet-network + - rivet-network-to-core + depends_on: + clickhouse: + condition: service_healthy + vector-client: + restart: unless-stopped + image: timberio/vector:0.48.0-distroless-static + command: '-C /etc/vector' + volumes: + - vector-client-data-local:/var/lib/vector + - ./vector-client:/etc/vector + networks: + - rivet-network + depends_on: + vector-server: + condition: service_started + otel-collector-server: + image: otel/opentelemetry-collector-contrib:latest + restart: unless-stopped + command: '--config=/etc/otel/config.yaml' + volumes: + - ./otel-collector-server/config.yaml:/etc/otel/config.yaml:ro + environment: + - CLICKHOUSE_PASSWORD=default + depends_on: + clickhouse: + condition: service_healthy + networks: + - rivet-network + - rivet-network-to-core + otel-collector-client: + image: otel/opentelemetry-collector-contrib:latest + restart: unless-stopped + command: '--config=/etc/otel/config.yaml' + volumes: + - ./otel-collector-client/config.yaml:/etc/otel/config.yaml:ro + depends_on: + otel-collector-server: + condition: service_started + networks: + - rivet-network + rivet-engine-0: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: /usr/bin/rivet-engine start + environment: + - RUST_LOG_ANSI_COLOR=1 + - RIVET_OTEL_ENABLED=1 + - RIVET_OTEL_SAMPLER_RATIO=1 + - RIVET_OTEL_GRPC_ENDPOINT=http://otel-collector-client:4317 + stop_grace_period: 0s + depends_on: + vector-client: + condition: service_started + otel-collector-client: + condition: service_started + postgres: + condition: service_healthy + volumes: + - ./rivet-engine/0/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network + - rivet-network-to-core + - rivet-network-engine-peer + ports: + - '6420:6420' + healthcheck: + test: + - CMD + - curl + - '-f' + - http://127.0.0.1:6421/health + interval: 2s + timeout: 10s + retries: 10 + start_period: 30s + rivet-engine-1: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: /usr/bin/rivet-engine start + environment: + - RUST_LOG_ANSI_COLOR=1 + - RIVET_OTEL_ENABLED=1 + - RIVET_OTEL_SAMPLER_RATIO=1 + - RIVET_OTEL_GRPC_ENDPOINT=http://otel-collector-client:4317 + stop_grace_period: 0s + depends_on: + vector-client: + condition: service_started + otel-collector-client: + condition: service_started + postgres: + condition: service_healthy + volumes: + - ./rivet-engine/1/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network + - rivet-network-to-core + - rivet-network-engine-peer + healthcheck: + test: + - CMD + - curl + - '-f' + - http://127.0.0.1:6421/health + interval: 2s + timeout: 10s + retries: 10 + start_period: 30s + rivet-engine-2: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: /usr/bin/rivet-engine start + environment: + - RUST_LOG_ANSI_COLOR=1 + - RIVET_OTEL_ENABLED=1 + - RIVET_OTEL_SAMPLER_RATIO=1 + - RIVET_OTEL_GRPC_ENDPOINT=http://otel-collector-client:4317 + stop_grace_period: 0s + depends_on: + vector-client: + condition: service_started + otel-collector-client: + condition: service_started + postgres: + condition: service_healthy + volumes: + - ./rivet-engine/2/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network + - rivet-network-to-core + - rivet-network-engine-peer + healthcheck: + test: + - CMD + - curl + - '-f' + - http://127.0.0.1:6421/health + interval: 2s + timeout: 10s + retries: 10 + start_period: 30s + runner-0: + build: + context: ../.. + dockerfile: sdks/typescript/test-runner/Dockerfile + platform: linux/amd64 + restart: unless-stopped + environment: + - RIVET_ENDPOINT=http://rivet-engine-0:6420 + - RUNNER_HOST=runner-0 + stop_grace_period: 4s + ports: + - '5050:5050' + depends_on: + rivet-engine-0: + condition: service_healthy + networks: + - rivet-network + runner-1: + build: + context: ../.. + dockerfile: sdks/typescript/test-runner/Dockerfile + platform: linux/amd64 + restart: unless-stopped + environment: + - RIVET_ENDPOINT=http://rivet-engine-0:6420 + - RUNNER_HOST=runner-1 + stop_grace_period: 4s + depends_on: + rivet-engine-0: + condition: service_healthy + networks: + - rivet-network + runner-2: + build: + context: ../.. + dockerfile: sdks/typescript/test-runner/Dockerfile + platform: linux/amd64 + restart: unless-stopped + environment: + - RIVET_ENDPOINT=http://rivet-engine-0:6420 + - RUNNER_HOST=runner-2 + stop_grace_period: 4s + depends_on: + rivet-engine-0: + condition: service_healthy + networks: + - rivet-network +networks: + rivet-core-network: + driver: bridge + rivet-network: + driver: bridge + rivet-network-engine-peer: + driver: bridge + rivet-network-to-core: + driver: bridge +volumes: + clickhouse-data: null + grafana-data: null + postgres-data: null + vector-server-data-local: null + vector-client-data-local: null diff --git a/docker/dev-multinode/grafana/dashboards/api.json b/docker/dev-multinode/grafana/dashboards/api.json new file mode 100644 index 0000000000..34004bf134 --- /dev/null +++ b/docker/dev-multinode/grafana/dashboards/api.json @@ -0,0 +1,1172 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 7, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 24, + "panels": [], + "title": "API", + "type": "row" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 26, + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_api_request_duration'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Request Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 27, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_api_request_pending'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Requests Pending", + "transformations": [ + { + "id": "groupingToMatrix", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 10 + }, + "id": 32, + "interval": "15s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n sum(Sum) / sum(Count) as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nHAVING sum(Count) > 0\nORDER BY time", + "refId": "A" + } + ], + "title": "Duration (avg)", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 10 + }, + "id": 33, + "interval": "15s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label, bounds, idx\nORDER BY time", + "refId": "A" + } + ], + "title": "Duration (p95)", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "bounds" + } + }, + { + "id": "convertFieldType", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 16, + "y": 10 + }, + "id": 34, + "interval": "15s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n Attributes['method'] as method,\n Attributes['path'] as path,\n histogramQuantile(arrayZip(ExplicitBounds, BucketCounts), 0.99) as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND Attributes['watch'] = '0'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, method, path\nORDER BY time", + "refId": "A" + } + ], + "title": "Duration (p99)", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 19 + }, + "id": 25, + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n sum(Value) / $__interval_ms * 1000 as value\n -- (\n -- SELECT\n -- sum(Value) / $__interval_ms * 1000 as value\n -- FROM otel.otel_metrics_sum\n -- WHERE MetricName = 'rivet_api_request_total'\n -- AND $__conditionalAll(Attributes['path'], $path)\n -- AND $__conditionalAll(Attributes['method'], $method)\n -- AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n -- AND $__timeFilter(TimeUnix)\n -- ) as prev_value\n -- lagInFrame(value, 1, value) OVER (ORDER BY time) as previous_value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_api_request_total'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Request Rate", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 19 + }, + "id": 28, + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Name", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}: {{status}} ({{error_code}})", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path'], ': ',\n Attributes['status'], ' (',\n Attributes['error_code'], ')'\n ) as label,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_api_request_errors'\n AND Attributes['status'] LIKE '4%'\n AND Attributes['error_code'] NOT IN ('API_CANCELLED', 'CAPTCHA_CAPTCHA_REQUIRED')\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Error Rate (4xx)", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\label" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 16, + "y": 19 + }, + "id": 31, + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}: {{status}} ({{error_code}})", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path'], ': ',\n Attributes['error_code'], ' (',\n Attributes['status'], ')'\n ) as label,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_api_request_errors'\n AND Attributes['status'] LIKE '5%'\n AND Attributes['error_code']-- NOT IN ('API_CANCELLED', 'CAPTCHA_CAPTCHA_REQUIRED')\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Error Rate (5xx)", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "log": 2, + "type": "log" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "percent" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 28 + }, + "id": 35, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{method}} {{path}}: {{status}} {{error_code}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['method'] as method,\n Attributes['path'] as path,\n Attributes['status'] as status,\n Attributes['error_code'] as error_code,\n sum(Count) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND (Attributes['status'] = '200' OR Attributes['status'] LIKE '5%')\n AND Attributes['error_code']-- NOT IN ('API_CANCELLED', 'CAPTCHA_CAPTCHA_REQUIRED')\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, method, path, status, error_code\nORDER BY time", + "refId": "A" + } + ], + "title": "200 vs 5xx (4xx excluded)", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "30s", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request_errors' ORDER BY datacenter_id", + "includeAll": true, + "label": "Datacenter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request_errors' ORDER BY datacenter_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['path'] as path FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) ORDER BY path", + "includeAll": true, + "label": "Path", + "multi": true, + "name": "path", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['path'] as path FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) ORDER BY path", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['method'] as method FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) AND $__conditionalAll(Attributes['path'], $path) ORDER BY method", + "includeAll": true, + "label": "Method", + "multi": true, + "name": "method", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['method'] as method FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) AND $__conditionalAll(Attributes['path'], $path) ORDER BY method", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-24h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "API", + "uid": "feg8y72gpm2o0c", + "version": 1, + "weekStart": "" +} diff --git a/docker/dev-multinode/grafana/dashboards/cache.json b/docker/dev-multinode/grafana/dashboards/cache.json new file mode 100644 index 0000000000..5d762023ea --- /dev/null +++ b/docker/dev-multinode/grafana/dashboards/cache.json @@ -0,0 +1,1176 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 4, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 10, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n CASE\n WHEN ResourceAttributes['datacenter_id'] != '' AND ResourceAttributes['server_id'] != '' THEN concat(ResourceAttributes['datacenter_id'], ' - ', ResourceAttributes['server_id'])\n ELSE 'Route Cache Size'\n END as label,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_route_cache_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Route Cache Size", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\label" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 11, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_rate_limiter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Rate Limiters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 12, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_in_flight_counter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "In-Flight Counters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 8 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_tcp_connection_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active TCP Connections", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 8 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_tcp_connection'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "TCP Connection Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 8 + }, + "id": 1, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_tcp_connection_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "TCP Connection Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 16 + }, + "id": 7, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_proxy_request_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Proxy Requests", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 16 + }, + "id": 8, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_proxy_request'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Proxy Request Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 16 + }, + "id": 9, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_proxy_request_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Proxy Request Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 24 + }, + "id": 6, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_resolve_route_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Resolve Route Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "description": "", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "description": "", + "includeAll": true, + "label": "Dataceter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "description": "", + "includeAll": true, + "label": "Server ID", + "multi": true, + "name": "server_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Rivet Guard", + "uid": "cen785ige8fswd", + "version": 1, + "weekStart": "" +} diff --git a/docker/dev-multinode/grafana/dashboards/futures.json b/docker/dev-multinode/grafana/dashboards/futures.json new file mode 100644 index 0000000000..0c992c4bcb --- /dev/null +++ b/docker/dev-multinode/grafana/dashboards/futures.json @@ -0,0 +1,208 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_instrumented_future_duration'\n AND $__conditionalAll(Attributes['name'], $name)\n AND $__conditionalAll(Attributes['location'], $location)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Instrumented Future Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "30s", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['name'] as name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY name", + "includeAll": true, + "label": "Name", + "multi": true, + "name": "name", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['name'] as name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY name", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['location'] as location FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY location", + "includeAll": true, + "label": "Location", + "multi": true, + "name": "location", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['location'] as location FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY location", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Futures", + "version": 0, + "weekStart": "" +} \ No newline at end of file diff --git a/docker/dev-multinode/grafana/dashboards/gasoline.json b/docker/dev-multinode/grafana/dashboards/gasoline.json new file mode 100644 index 0000000000..bac8c7b6da --- /dev/null +++ b/docker/dev-multinode/grafana/dashboards/gasoline.json @@ -0,0 +1,2583 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": 3, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{workflow_name}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_active'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Running Workflows", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 3, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{workflow_name}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_sleeping'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Sleeping Workflows", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 1, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{workflow_name}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_dead'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Dead Workflows", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 6, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "({{workflow_name}}) {{error_code}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n Attributes['error_code'] as error_code,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_dead'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name, error_code\nORDER BY time", + "refId": "A" + } + ], + "title": "Dead Workflow Errors", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "__auto", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n count(*) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_worker_last_ping'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Workers", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "datacenter_id", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\datacenter_id" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 4, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{signal_name}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['signal_name'] as signal_name,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_signal_pending'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, signal_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Pending Signals", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "signal_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\signal_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 10, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size", + "value": "" + }, + "yBuckets": { + "mode": "size", + "scale": { + "log": 2, + "type": "log" + }, + "value": "" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "hide": false, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_signal_recv_lag'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Signal Receive Lag", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 24 + }, + "id": 11, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_signal_pull_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY\n Time, le\nORDER BY\n Time, le", + "refId": "A" + } + ], + "title": "Pull Signals Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 32 + }, + "id": 13, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "instant": false, + "legendFormat": "{{worker_instance_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['worker_instance_id'] as worker_instance_id,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_last_pull_workflows_duration'\n AND ResourceAttributes['cluster_id'] LIKE '${cluster_id:regex}'\n AND ResourceAttributes['datacenter_id'] LIKE '${datacenter_id:regex}'\n AND $__timeFilter(TimeUnix)\nGROUP BY time, worker_instance_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Last Pull Workflows Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "worker_instance_id", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\worker_instance_id" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 32 + }, + "id": 14, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "instant": false, + "legendFormat": "{{worker_instance_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['worker_instance_id'] as worker_instance_id,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_last_pull_workflows_history_duration'\n AND ResourceAttributes['cluster_id'] LIKE '${cluster_id:regex}'\n AND ResourceAttributes['datacenter_id'] LIKE '${datacenter_id:regex}'\n AND $__timeFilter(TimeUnix)\nGROUP BY time, worker_instance_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Last Pull Workflows History Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "worker_instance_id", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\worker_instance_id" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 40 + }, + "id": 23, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_pull_workflows_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Pull Workflows Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 40 + }, + "id": 24, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_pull_workflows_history_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Pull Workflows History Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 48 + }, + "id": 16, + "panels": [], + "title": "Steps", + "type": "row" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 49 + }, + "id": 12, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_activity_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Activity Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 49 + }, + "id": 9, + "interval": "15s", + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{activity_name}}: {{error_code}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['activity_name'] as activity_name,\n Attributes['error_code'] as error_code,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_gasoline_activity_errors'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, activity_name, error_code\nORDER BY time", + "refId": "A" + } + ], + "title": "Activity Error Rate", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "activity_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\activity_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 58 + }, + "id": 21, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_loop_iteration_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Loop Upsert Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ev/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 58 + }, + "id": 25, + "interval": "15s", + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "legendFormat": "{{workflow_name}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n sum(Count) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_gasoline_loop_iteration_duration'\n AND Attributes['workflow_name'] LIKE '${workflow_name:regex}'\n AND ResourceAttributes['cluster_id'] LIKE '${cluster_id:regex}'\n AND ResourceAttributes['datacenter_id'] LIKE '${datacenter_id:regex}'\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Loop Events Per Second", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 67 + }, + "id": 17, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_message_send_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Message Send Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 67 + }, + "id": 20, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_signal_send_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Signal Send Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 76 + }, + "id": 22, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_find_workflows_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Find Workflows Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 76 + }, + "id": 19, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_workflow_dispatch_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Sub Workflow Dispatch Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "5s", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY cluster_id", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY cluster_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY datacenter_id", + "includeAll": true, + "label": "Datacenter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY datacenter_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['workflow_name'] as workflow_name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_gasoline_signal_recv_lag' ORDER BY workflow_name", + "includeAll": true, + "label": "Workflow Name", + "multi": true, + "name": "workflow_name", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['workflow_name'] as workflow_name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_gasoline_signal_recv_lag' ORDER BY workflow_name", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Gasoline", + "uid": "636d22f9-d18f-4086-8b45-7c50886a105c", + "version": 1, + "weekStart": "" +} diff --git a/docker/dev-multinode/grafana/dashboards/guard.json b/docker/dev-multinode/grafana/dashboards/guard.json new file mode 100644 index 0000000000..fb657d441b --- /dev/null +++ b/docker/dev-multinode/grafana/dashboards/guard.json @@ -0,0 +1,1150 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 115, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 10, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_route_cache_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Route Cache Size", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 11, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_rate_limiter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Rate Limiters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 12, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_in_flight_counter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "In-Flight Counters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 8 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_tcp_connection_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active TCP Connections", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 8 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_tcp_connection'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "TCP Connection Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 8 + }, + "id": 1, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_tcp_connection_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "TCP Connection Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 16 + }, + "id": 7, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_proxy_request_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Proxy Requests", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 16 + }, + "id": 8, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_proxy_request'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Proxy Request Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 16 + }, + "id": 9, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_proxy_request_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Proxy Request Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 24 + }, + "id": 6, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_resolve_route_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Resolve Route Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "description": "", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "description": "", + "includeAll": true, + "label": "Dataceter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "description": "", + "includeAll": true, + "label": "Server ID", + "multi": true, + "name": "server_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Rivet Guard", + "uid": "cen785ige8fswd", + "version": 1, + "weekStart": "" +} diff --git a/docker/dev-multinode/grafana/dashboards/tokio.json b/docker/dev-multinode/grafana/dashboards/tokio.json new file mode 100644 index 0000000000..efa5e4b49f --- /dev/null +++ b/docker/dev-multinode/grafana/dashboards/tokio.json @@ -0,0 +1,1009 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": 81, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 24, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_global_queue_depth'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Global Queue Depth", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 27, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_worker_local_queue_depth'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Worker Queue Depth", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 11, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_tokio_task_poll_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Task Poll Times", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 26, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_worker_overflow_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Worker Overflow Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 23, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_future_schedule_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Future Schedule Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 25, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_thread_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Thread Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "tasks/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 28, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_tokio_task'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Task Spawn Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 24 + }, + "id": 29, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_active_task_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Tasks", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "5s", + "schemaVersion": 40, + "templating": { + "list": [ + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY cluster_id", + "description": "", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY cluster_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY datacenter_id", + "description": "", + "includeAll": true, + "label": "Dataceter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY datacenter_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY server_id", + "description": "", + "includeAll": true, + "label": "Server ID", + "multi": true, + "name": "server_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY server_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['pool_type'] as pool_type FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY pool_type", + "includeAll": true, + "label": "Pool", + "multi": true, + "name": "pool_type", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['pool_type'] as pool_type FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY pool_type", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Tokio", + "uid": "636d22f9-d18f-4086-8b45-7c50886a105d", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/docker/dev-multinode/grafana/dashboards/traces.json b/docker/dev-multinode/grafana/dashboards/traces.json new file mode 100644 index 0000000000..64f6b552c9 --- /dev/null +++ b/docker/dev-multinode/grafana/dashboards/traces.json @@ -0,0 +1,979 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 21, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 9, + "panels": [], + "title": "Traces", + "type": "row" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "bars", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 0, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 1 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-traces" + }, + "editorType": "sql", + "format": 0, + "meta": { + "builderOptions": { + "aggregates": [ + { + "aggregateType": "count", + "column": "" + } + ], + "columns": [ + { + "hint": "time", + "name": "Timestamp", + "type": "DateTime64(9)" + } + ], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "hint": "time", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "ServiceName" + ], + "limit": 10000, + "mode": "trend", + "orderBy": [], + "queryType": "timeseries", + "table": "otel_traces" + } + }, + "pluginVersion": "4.0.6", + "queryType": "timeseries", + "rawSql": "SELECT\r\n $__timeInterval(Timestamp) as time,\r\n ServiceName,\r\n count() as ` `\r\nFROM otel.otel_traces\r\nWHERE\r\n ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )\r\n AND $__conditionalAll(ServiceName, $service_name)\r\n AND $__conditionalAll(SpanName, $span_name)\r\n AND (($ray_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['ray_id'], $ray_id))\r\n AND (($workflow_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['workflow_id'], $workflow_id))\r\nGROUP BY ServiceName, time\r\nORDER BY time ASC\r\nLIMIT 100000\r\n", + "refId": "A" + } + ], + "title": "Traces per Service", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Trace ID" + }, + "properties": [ + { + "id": "custom.width", + "value": 77 + }, + { + "id": "links", + "value": [ + { + "title": "__value.raw", + "url": "/d/8klBUGfVk/otel-traces?${__url_time_range}&${service_name:queryparam}&var-trace_id=${__value.raw}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Service Name" + }, + "properties": [ + { + "id": "custom.width", + "value": 130 + }, + { + "id": "links", + "value": [ + { + "title": "__value.raw", + "url": "/d/8klBUGfVk/otel-traces?${__url_time_range}&${trace_id:queryparam}&var-serviceName=${__value.raw}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Duration" + }, + "properties": [ + { + "id": "unit", + "value": "ms" + }, + { + "id": "custom.cellOptions", + "value": { + "mode": "lcd", + "type": "gauge", + "valueDisplayMode": "text" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "timestamp" + }, + "properties": [ + { + "id": "custom.width", + "value": 216 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Service Tags" + }, + "properties": [ + { + "id": "custom.inspect", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "timestamp" + }, + "properties": [ + { + "id": "custom.width", + "value": 248 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "timestamp" + }, + "properties": [ + { + "id": "custom.width", + "value": 234 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": " " + }, + "properties": [ + { + "id": "custom.width", + "value": 49 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Span Name" + }, + "properties": [ + { + "id": "custom.width", + "value": 140 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Ts" + }, + "properties": [ + { + "id": "custom.width", + "value": 168 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "URI/workflow_id/actor_id" + }, + "properties": [ + { + "id": "custom.width", + "value": 920 + } + ] + } + ] + }, + "gridPos": { + "h": 13, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 4, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Duration" + } + ] + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorType": "sql", + "format": 1, + "meta": { + "builderOptions": { + "columns": [], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "queryType": "table", + "table": "otel_traces" + } + }, + "pluginVersion": "4.9.0", + "queryType": "table", + "rawSql": "SELECT\r\n (argMin(StatusCode, Timestamp) = 'Error' ? '⚠️' : '') as ` `,\r\n min(Timestamp) as Ts,\r\n TraceId as `Trace ID`,\r\n argMin(ServiceName, Timestamp) as `Service Name`,\r\n argMin(SpanName, Timestamp) as `Span Name`,\r\n argMin(coalesce(NULLIF(SpanAttributes['uri'], ''), NULLIF(SpanAttributes['workflow_id'], ''), SpanAttributes['actor_id']), Timestamp) as `URI/workflow_id/actor_id`,\r\n divide(max(Duration), 1000000) as Duration\r\nFROM otel.otel_traces\r\nWHERE\r\n $__conditionalAll(ServiceName, $service_name)\r\n AND $__conditionalAll(SpanName, $span_name)\r\n AND (($ray_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['ray_id'], $ray_id))\r\n AND (($workflow_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['workflow_id'], $workflow_id))\r\n AND ServiceName != 'loadgenerator'\r\n AND ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )\r\nGROUP BY TraceId\r\nORDER BY Duration DESC\r\nLIMIT 100\r\n", + "refId": "A" + } + ], + "title": "Traces", + "type": "table" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, + "gridPos": { + "h": 17, + "w": 24, + "x": 0, + "y": 23 + }, + "id": 6, + "options": { + "spanFilters": { + "criticalPathOnly": false, + "matchesOnly": false, + "serviceNameOperator": "=", + "spanNameOperator": "=" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "builderOptions": { + "columns": [ + { + "hint": "trace_id", + "name": "TraceId" + }, + { + "hint": "trace_span_id", + "name": "SpanId" + }, + { + "hint": "trace_parent_span_id", + "name": "ParentSpanId" + }, + { + "hint": "trace_service_name", + "name": "ServiceName" + }, + { + "hint": "trace_operation_name", + "name": "SpanName" + }, + { + "hint": "time", + "name": "Timestamp" + }, + { + "hint": "trace_duration_time", + "name": "Duration" + }, + { + "hint": "trace_tags", + "name": "SpanAttributes" + }, + { + "hint": "trace_service_tags", + "name": "ResourceAttributes" + }, + { + "hint": "trace_status_code", + "name": "StatusCode" + } + ], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "hint": "time", + "key": "", + "operator": "WITH IN DASHBOARD TIME RANGE", + "type": "datetime" + }, + { + "condition": "AND", + "filterType": "custom", + "hint": "trace_duration_time", + "key": "", + "operator": ">", + "type": "UInt64", + "value": 0 + }, + { + "condition": "AND", + "filterType": "custom", + "hint": "trace_service_name", + "key": "", + "operator": "IS ANYTHING", + "type": "string", + "value": "" + } + ], + "limit": 1000, + "meta": { + "isTraceIdMode": true, + "otelEnabled": true, + "otelVersion": "latest", + "traceDurationUnit": "nanoseconds", + "traceId": "${trace_id}" + }, + "mode": "list", + "orderBy": [ + { + "default": true, + "dir": "DESC", + "hint": "time", + "name": "" + }, + { + "default": true, + "dir": "DESC", + "hint": "trace_duration_time", + "name": "" + } + ], + "queryType": "traces", + "table": "otel_traces" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-traces" + }, + "editorType": "builder", + "format": 3, + "meta": { + "builderOptions": { + "columns": [], + "database": "", + "limit": 100, + "mode": "list", + "queryType": "table", + "table": "" + } + }, + "pluginVersion": "4.0.6", + "queryType": "traces", + "rawSql": "WITH\n\t(SELECT min(Start) FROM otel.otel_traces_trace_id_ts WHERE $__conditionalAll(TraceId, $trace_id)) as trace_start,\n\t(SELECT max(End) + 1 FROM otel.otel_traces_trace_id_ts WHERE $__conditionalAll(TraceId, $trace_id)) as trace_end\nSELECT\n\tTraceId as traceID,\n\tSpanId as spanID,\n\tParentSpanId as parentSpanID,\n\tServiceName as serviceName,\n\tSpanName as operationName, Timestamp as startTime,\n\tmultiply(Duration, 0.000001) as duration,\n\tarrayMap(key -> map('key', key, 'value', SpanAttributes[key]), mapKeys(SpanAttributes)) as tags,\n\tarrayMap(key -> map('key', key, 'value', ResourceAttributes[key]), mapKeys(ResourceAttributes)) as serviceTags,\n\tarrayMap((name, timestamp, attributes) -> tuple(name, toString(multiply(toUnixTimestamp64Nano(timestamp), 0.000001)), arrayMap( key -> map('key', key, 'value', attributes[key]), mapKeys(attributes)))::Tuple(name String, timestamp String, fields Array(Map(String, String))), `Events.Name`, `Events.Timestamp`, `Events.Attributes`) AS logs,\n\tarrayMap((traceID, spanID, attributes) -> tuple(traceID, spanID, arrayMap(key -> map('key', key, 'value', attributes[key]), mapKeys(attributes)))::Tuple(traceID String, spanID String, tags Array(Map(String, String))), `Links.TraceId`, `Links.SpanId`, `Links.Attributes`) AS references\nFROM otel.otel_traces\nWHERE\n\t$__conditionalAll(traceID, $trace_id) AND startTime >= trace_start AND startTime <= trace_end AND ( Duration > 0 )\nORDER BY Timestamp DESC, Duration DESC\nLIMIT 1000", + "refId": "A" + } + ], + "title": "Trace Details", + "type": "traces" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "bars", + "fillOpacity": 24, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 8, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-traces" + }, + "editorType": "sql", + "format": 0, + "meta": { + "builderOptions": { + "aggregates": [ + { + "aggregateType": "count", + "column": "" + } + ], + "columns": [ + { + "hint": "time", + "name": "Timestamp", + "type": "DateTime64(9)" + } + ], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "hint": "time", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "ServiceName" + ], + "limit": 10000, + "mode": "trend", + "orderBy": [], + "queryType": "timeseries", + "table": "otel_traces" + } + }, + "pluginVersion": "4.0.6", + "queryType": "timeseries", + "rawSql": "SELECT\r\n $__timeInterval(Timestamp) as time,\r\n count(*) as ` `,\r\n ServiceName\r\nFROM otel.otel_traces\r\nWHERE\r\n $__conditionalAll(TraceId, $trace_id)\r\n AND ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )\r\n AND $__conditionalAll(ServiceName, $service_name)\r\n AND $__conditionalAll(SpanName, $span_name)\r\n AND (($ray_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['ray_id'], $ray_id)\r\n AND (($workflow_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['workflow_id'], $workflow_id))\r\n AND StatusCode IN ('Error', 'STATUS_CODE_ERROR')\r\n AND ServiceName != 'loadgenerator' GROUP BY ServiceName, time\r\nORDER BY time ASC\r\nLIMIT 100000", + "refId": "A" + } + ], + "title": "Error rates", + "type": "timeseries" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 49 + }, + "id": 10, + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 61 + }, + "id": 11, + "options": { + "dedupStrategy": "none", + "enableInfiniteScrolling": false, + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": true, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "builderOptions": { + "columns": [ + { + "hint": "time", + "name": "Timestamp", + "type": "DateTime64(9)" + }, + { + "hint": "log_level", + "name": "SeverityText", + "type": "LowCardinality(String)" + }, + { + "hint": "log_message", + "name": "Body", + "type": "String" + } + ], + "database": "otel", + "filters": [], + "limit": 1000, + "meta": { + "logMessageLike": "", + "otelVersion": "latest" + }, + "mode": "list", + "orderBy": [], + "queryType": "logs", + "table": "otel_logs" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorType": "builder", + "format": 2, + "pluginVersion": "4.0.6", + "rawSql": "SELECT Timestamp as timestamp, Body as body, SeverityText as level FROM \"otel\".\"otel_logs\" LIMIT 1000", + "refId": "A" + } + ], + "title": "Trace Logs", + "type": "logs" + } + ], + "title": "Logs", + "type": "row" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "ClickHouse", + "value": "ClickHouse" + }, + "includeAll": false, + "label": "ClickHouse instance", + "name": "datasource", + "options": [], + "query": "grafana-clickhouse-datasource", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ServiceName FROM otel.otel_traces", + "includeAll": true, + "label": "Service Name", + "multi": true, + "name": "service_name", + "options": [], + "query": "SELECT DISTINCT ServiceName FROM otel.otel_traces", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT TraceId FROM otel.otel_traces WHERE ParentSpanId = '' LIMIT 100", + "includeAll": true, + "label": "Trace ID", + "name": "trace_id", + "options": [], + "query": "SELECT DISTINCT TraceId FROM otel.otel_traces WHERE ParentSpanId = '' LIMIT 100", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT SpanName FROM otel.otel_traces WHERE $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "description": "", + "includeAll": true, + "label": "Span", + "multi": true, + "name": "span_name", + "options": [], + "query": "SELECT DISTINCT SpanName FROM otel.otel_traces WHERE $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "allValue": "'All'", + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT SpanAttributes['ray_id'] FROM otel.otel_traces WHERE SpanAttributes['ray_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "description": "", + "includeAll": true, + "label": "Ray ID", + "multi": true, + "name": "ray_id", + "options": [], + "query": "SELECT DISTINCT SpanAttributes['ray_id'] FROM otel.otel_traces WHERE SpanAttributes['ray_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "allValue": "'All'", + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT SpanAttributes['workflow_id'] FROM otel.otel_traces WHERE SpanAttributes['workflow_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "description": "", + "includeAll": true, + "label": "Workflow ID", + "multi": true, + "name": "workflow_id", + "options": [], + "query": "SELECT DISTINCT SpanAttributes['workflow_id'] FROM otel.otel_traces WHERE SpanAttributes['workflow_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "America/Los_Angeles", + "title": "Traces", + "uid": "8klBUGfVk", + "version": 2, + "weekStart": "" +} diff --git a/docker/dev-multinode/grafana/grafana.ini b/docker/dev-multinode/grafana/grafana.ini new file mode 100644 index 0000000000..1bd9bfe697 --- /dev/null +++ b/docker/dev-multinode/grafana/grafana.ini @@ -0,0 +1,14 @@ +[server] +http_port = 3000 +root_url = http://localhost:3100 + +[security] +admin_user = admin +admin_password = admin + +[auth.anonymous] +enabled = true +org_role = Viewer + +[dashboards] +default_home_dashboard_path = /var/lib/grafana/dashboards/api.json diff --git a/docker/dev-multinode/grafana/provisioning/dashboards/dashboards.yaml b/docker/dev-multinode/grafana/provisioning/dashboards/dashboards.yaml new file mode 100644 index 0000000000..7d91589dc7 --- /dev/null +++ b/docker/dev-multinode/grafana/provisioning/dashboards/dashboards.yaml @@ -0,0 +1,10 @@ +apiVersion: 1 +providers: + - name: rivet-dashboards + orgId: 1 + folder: '' + type: file + disableDeletion: false + updateIntervalSeconds: 10 + options: + path: /var/lib/grafana/dashboards diff --git a/docker/dev-multinode/grafana/provisioning/datasources/datasources.yaml b/docker/dev-multinode/grafana/provisioning/datasources/datasources.yaml new file mode 100644 index 0000000000..f66d3bf036 --- /dev/null +++ b/docker/dev-multinode/grafana/provisioning/datasources/datasources.yaml @@ -0,0 +1,30 @@ +apiVersion: 1 +datasources: + - name: ClickHouse + uid: clickhouse + type: grafana-clickhouse-datasource + access: proxy + secureJsonData: + password: default + jsonData: + version: 2.0.0 + host: clickhouse + port: 9300 + defaultDatabase: default + protocol: http + secure: false + username: default + validateSql: true + logs: + otelEnabled: true + otelVersion: 1.2.9 + defaultDatabase: otel + defaultTable: otel_logs + timeColumn: TimestampTime + messageColumn: Body + levelColumn: SeverityText + traces: + otelEnabled: true + otelVersion: 1.2.9 + defaultDatabase: otel + defaultTable: otel_traces diff --git a/docker/dev-multinode/otel-collector-client/config.yaml b/docker/dev-multinode/otel-collector-client/config.yaml new file mode 100644 index 0000000000..6e963d5edf --- /dev/null +++ b/docker/dev-multinode/otel-collector-client/config.yaml @@ -0,0 +1,39 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + http: + endpoint: 0.0.0.0:4318 +processors: + batch: + timeout: 5s + send_batch_size: 10000 +exporters: + otlp/server: + endpoint: otel-collector-server:4317 + tls: + insecure: true +service: + pipelines: + logs: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server + traces: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server + metrics: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server diff --git a/docker/dev-multinode/otel-collector-server/config.yaml b/docker/dev-multinode/otel-collector-server/config.yaml new file mode 100644 index 0000000000..a74179019e --- /dev/null +++ b/docker/dev-multinode/otel-collector-server/config.yaml @@ -0,0 +1,61 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 +processors: + batch: + timeout: 5s + send_batch_size: 10000 +exporters: + clickhouse: + endpoint: http://clickhouse:9300 + database: otel + username: default + password: ${env:CLICKHOUSE_PASSWORD} + async_insert: true + ttl: 72h + compress: lz4 + create_schema: true + logs_table_name: otel_logs + traces_table_name: otel_traces + timeout: 5s + metrics_tables: + gauge: + name: otel_metrics_gauge + sum: + name: otel_metrics_sum + summary: + name: otel_metrics_summary + histogram: + name: otel_metrics_histogram + exponential_histogram: + name: otel_metrics_exp_histogram + retry_on_failure: + enabled: true + initial_interval: 5s + max_interval: 30s + max_elapsed_time: 300s +service: + pipelines: + logs: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse + traces: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse + metrics: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse diff --git a/docker/dev-multinode/postgres/init-db.sh b/docker/dev-multinode/postgres/init-db.sh new file mode 100755 index 0000000000..6b57fcfef7 --- /dev/null +++ b/docker/dev-multinode/postgres/init-db.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -e + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + CREATE DATABASE rivet_engine; +EOSQL diff --git a/docker/dev-multinode/rivet-engine/0/config.jsonc b/docker/dev-multinode/rivet-engine/0/config.jsonc new file mode 100644 index 0000000000..a1d2990f85 --- /dev/null +++ b/docker/dev-multinode/rivet-engine/0/config.jsonc @@ -0,0 +1,56 @@ +{ + "guard": { + "port": 6420 + }, + "api_public": { + "lan_host": "rivet-engine-0", + "host": "0.0.0.0", + "port": 6421 + }, + "api_peer": { + "host": "0.0.0.0", + "port": 6422 + }, + "pegboard": { + "lan_host": "rivet-engine-0", + "host": "0.0.0.0", + "port": 6423 + }, + "logs": {}, + "topology": { + "datacenter_label": 1, + "datacenters": [ + { + "name": "local", + "datacenter_label": 1, + "is_leader": true, + "api_peer_url": "http://rivet-engine-0:6422", + "guard_url": "http://rivet-engine-0:6420" + } + ] + }, + "postgres": { + "url": "postgresql://postgres:postgres@postgres:5432/rivet_engine" + }, + "cache": { + "driver": "in_memory" + }, + "clickhouse": { + "http_url": "http://clickhouse:9300", + "native_url": "http://clickhouse:9301", + "username": "system", + "password": "default", + "provision_users": { + "vector": { + "username": "vector", + "password": "vector", + "role": "write" + } + }, + "secure": false + }, + "vector_http": { + "host": "vector-client", + "port": 5022 + } +} \ No newline at end of file diff --git a/docker/dev-multinode/rivet-engine/1/config.jsonc b/docker/dev-multinode/rivet-engine/1/config.jsonc new file mode 100644 index 0000000000..a1d2990f85 --- /dev/null +++ b/docker/dev-multinode/rivet-engine/1/config.jsonc @@ -0,0 +1,56 @@ +{ + "guard": { + "port": 6420 + }, + "api_public": { + "lan_host": "rivet-engine-0", + "host": "0.0.0.0", + "port": 6421 + }, + "api_peer": { + "host": "0.0.0.0", + "port": 6422 + }, + "pegboard": { + "lan_host": "rivet-engine-0", + "host": "0.0.0.0", + "port": 6423 + }, + "logs": {}, + "topology": { + "datacenter_label": 1, + "datacenters": [ + { + "name": "local", + "datacenter_label": 1, + "is_leader": true, + "api_peer_url": "http://rivet-engine-0:6422", + "guard_url": "http://rivet-engine-0:6420" + } + ] + }, + "postgres": { + "url": "postgresql://postgres:postgres@postgres:5432/rivet_engine" + }, + "cache": { + "driver": "in_memory" + }, + "clickhouse": { + "http_url": "http://clickhouse:9300", + "native_url": "http://clickhouse:9301", + "username": "system", + "password": "default", + "provision_users": { + "vector": { + "username": "vector", + "password": "vector", + "role": "write" + } + }, + "secure": false + }, + "vector_http": { + "host": "vector-client", + "port": 5022 + } +} \ No newline at end of file diff --git a/docker/dev-multinode/rivet-engine/2/config.jsonc b/docker/dev-multinode/rivet-engine/2/config.jsonc new file mode 100644 index 0000000000..a1d2990f85 --- /dev/null +++ b/docker/dev-multinode/rivet-engine/2/config.jsonc @@ -0,0 +1,56 @@ +{ + "guard": { + "port": 6420 + }, + "api_public": { + "lan_host": "rivet-engine-0", + "host": "0.0.0.0", + "port": 6421 + }, + "api_peer": { + "host": "0.0.0.0", + "port": 6422 + }, + "pegboard": { + "lan_host": "rivet-engine-0", + "host": "0.0.0.0", + "port": 6423 + }, + "logs": {}, + "topology": { + "datacenter_label": 1, + "datacenters": [ + { + "name": "local", + "datacenter_label": 1, + "is_leader": true, + "api_peer_url": "http://rivet-engine-0:6422", + "guard_url": "http://rivet-engine-0:6420" + } + ] + }, + "postgres": { + "url": "postgresql://postgres:postgres@postgres:5432/rivet_engine" + }, + "cache": { + "driver": "in_memory" + }, + "clickhouse": { + "http_url": "http://clickhouse:9300", + "native_url": "http://clickhouse:9301", + "username": "system", + "password": "default", + "provision_users": { + "vector": { + "username": "vector", + "password": "vector", + "role": "write" + } + }, + "secure": false + }, + "vector_http": { + "host": "vector-client", + "port": 5022 + } +} \ No newline at end of file diff --git a/docker/dev-multinode/vector-client/vector.yaml b/docker/dev-multinode/vector-client/vector.yaml new file mode 100644 index 0000000000..a4ca8e5da5 --- /dev/null +++ b/docker/dev-multinode/vector-client/vector.yaml @@ -0,0 +1,31 @@ +# Vector Client Configuration for Datacenter: local +# This Vector instance runs on each server to collect local logs and forward them +# to the central Vector server aggregator. + +api: + enabled: true + address: 0.0.0.0:8686 +sources: + http_events: + type: http_server + address: 0.0.0.0:5022 + encoding: ndjson +transforms: {} +sinks: + vector_server: + type: vector + inputs: + - http_events + address: vector-server:6000 + version: '2' + buffer: + type: disk + max_size: 2147483648 + when_full: block + console_debug: + type: console + inputs: + - http_events + encoding: + codec: json + \ No newline at end of file diff --git a/docker/dev-multinode/vector-server/vector.yaml b/docker/dev-multinode/vector-server/vector.yaml new file mode 100644 index 0000000000..5dfdbff2f5 --- /dev/null +++ b/docker/dev-multinode/vector-server/vector.yaml @@ -0,0 +1,61 @@ +# Vector Server (Aggregator) Configuration +# This Vector instance acts as an aggregator that collects logs and metrics from all Vector clients +# across different datacenters and forwards them to ClickHouse and other sinks. + +api: + enabled: true + address: 0.0.0.0:8686 +sources: + vector: + type: vector + address: 0.0.0.0:6000 + version: '2' + tcp_json: + type: socket + mode: tcp + address: 0.0.0.0:6100 + decoding: + codec: json + http_json: + type: http_server + address: 0.0.0.0:6200 + encoding: json + vector_metrics: + type: internal_metrics + vector_logs: + type: internal_logs +transforms: + clickhouse_dynamic_events_filter: + type: filter + inputs: + - vector + condition: + type: vrl + source: .source == "clickhouse" + clickhouse_dynamic_events_transform: + type: remap + inputs: + - clickhouse_dynamic_events_filter + source: "# Extract and store metadata\n__database = .database\n__table = .table\n__columns = .columns\n\n# Create a new object with just the columns data\n. = {\n\t\"__database\": __database,\n\t\"__table\": __table,\n\t# By default insert namespace column since most tables include this\n\t\"namespace\": \"rivet\"\n}\n\t\n# Merge in the column data that should be inserted\n. = merge!(., __columns)\n" +sinks: + clickhouse_dynamic_events: + type: clickhouse + inputs: + - clickhouse_dynamic_events_transform + endpoint: http://clickhouse:9300 + database: '{{ __database }}' + table: '{{ __table }}' + compression: gzip + auth: + strategy: basic + user: system + password: default + batch: + max_events: 1000 + timeout_secs: 10 + console_vector_logs: + type: console + inputs: + - vector_logs + encoding: + codec: json diff --git a/docker/dev/.gitattributes b/docker/dev/.gitattributes new file mode 100644 index 0000000000..447edeb5c2 --- /dev/null +++ b/docker/dev/.gitattributes @@ -0,0 +1 @@ +. linguist-generated=true diff --git a/docker/dev/README.md b/docker/dev/README.md new file mode 100644 index 0000000000..07eaf1f4f7 --- /dev/null +++ b/docker/dev/README.md @@ -0,0 +1,74 @@ +# dev - Auto-generated Docker Compose Template + +> ! **Auto-generated**: This directory and its contents are automatically generated by `docker/template/`. Do not edit these files directly as your changes will be overwritten. + +## Overview + +This Docker Compose configuration provides a complete development environment for Rivet with the following services: + +- **Rivet Engine**: Main orchestration service +- **Rivet Shell**: Interactive shell for debugging +- **Runner**: Executes user code +- **ClickHouse**: Analytics and time-series database +- **PostgreSQL**: Relational database +- **Vector Server**: Log aggregation and processing +- **OpenTelemetry Collector**: Observability data collection + +## Port Configuration + +| Service | Port(s) | Description | +|---------|---------|-------------| +| Rivet Engine | 6420 | Public endpoint | +| Runner | 5050 | Code execution service | +| PostgreSQL | 5432 | Database | +| ClickHouse HTTP | 9300 | Database HTTP interface | +| ClickHouse Native | 9301 | Database native protocol | +| OpenTelemetry gRPC | 4317 | OTLP gRPC endpoint | +| OpenTelemetry HTTP | 4318 | OTLP HTTP endpoint | + +## Template Configuration + +**Template Name**: `dev` +**Base Port**: `6420` +**Network Mode**: `bridge` + +### Datacenters +- **1**: 1 engine(s), 1 runner(s) + +## Usage + +1. Start all services: + ```bash + docker-compose up -d + ``` + +2. Check service health: + ```bash + docker-compose ps + ``` + +3. View logs: + ```bash + docker-compose logs -f [service-name] + ``` + +4. Stop all services: + ```bash + docker-compose down + ``` + +## Generated Files + +This template generates the following files and directories: +- `docker-compose.yml` - Main Docker Compose configuration +- `core/` - Core services shared across datacenters: + - `clickhouse/` - ClickHouse configuration and initialization + - `vector-server/` - Vector aggregator configuration + - `otel-collector-server/` - OpenTelemetry Collector server configuration +- `datacenters/` - Datacenter-specific configurations: + - `1/` - Configuration for datacenter 1: + - `postgres/` - PostgreSQL setup scripts + - `rivet-engine/` - Rivet Engine configuration + - `vector-client/` - Vector client configuration + - `otel-collector-client/` - OpenTelemetry Collector client configuration +- `README.md` - This file diff --git a/docker/dev/clickhouse/client-config.xml b/docker/dev/clickhouse/client-config.xml new file mode 100644 index 0000000000..72f9850f4e --- /dev/null +++ b/docker/dev/clickhouse/client-config.xml @@ -0,0 +1,5 @@ + + + 9301 + 127.0.0.1 + \ No newline at end of file diff --git a/docker/dev/clickhouse/config.xml b/docker/dev/clickhouse/config.xml new file mode 100644 index 0000000000..e7ccd0480b --- /dev/null +++ b/docker/dev/clickhouse/config.xml @@ -0,0 +1,52 @@ + + + + debug + /var/log/clickhouse-server/clickhouse-server.log + /var/log/clickhouse-server/clickhouse-server.err.log + 1000M + 10 + + + :: + 9300 + 9301 + + + 9440 + 9010 + + 9009 + + 4096 + 3 + 100 + 8589934592 + 5368709120 + + /var/lib/clickhouse/ + /var/lib/clickhouse/tmp/ + /var/lib/clickhouse/user_files/ + /var/lib/clickhouse/access/ + + users.xml + default + default + UTC + + + + + + 3600 + 3600 + 60 + + + system + query_log
+ 7500 +
+ + *_dictionary.xml +
diff --git a/docker/dev/clickhouse/init/01-create-otel-table.sql b/docker/dev/clickhouse/init/01-create-otel-table.sql new file mode 100644 index 0000000000..2c7b9f7957 --- /dev/null +++ b/docker/dev/clickhouse/init/01-create-otel-table.sql @@ -0,0 +1,107 @@ +CREATE DATABASE IF NOT EXISTS otel; + +CREATE TABLE IF NOT EXISTS otel.otel_logs ( + Timestamp DateTime64(9) CODEC(Delta, ZSTD(1)), + ObservedTimestamp DateTime64(9) CODEC(Delta, ZSTD(1)), + TraceId String CODEC(ZSTD(1)), + SpanId String CODEC(ZSTD(1)), + TraceFlags UInt32 CODEC(ZSTD(1)), + SeverityText LowCardinality(String) CODEC(ZSTD(1)), + SeverityNumber Int32 CODEC(ZSTD(1)), + ServiceName LowCardinality(String) CODEC(ZSTD(1)), + Body String CODEC(ZSTD(1)), + ResourceSchemaUrl String CODEC(ZSTD(1)), + ResourceAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ScopeSchemaUrl String CODEC(ZSTD(1)), + ScopeName String CODEC(ZSTD(1)), + ScopeVersion String CODEC(ZSTD(1)), + ScopeAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + LogAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + INDEX idx_trace_id TraceId TYPE bloom_filter(0.001) GRANULARITY 1, + INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_key mapKeys(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_value mapValues(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_log_attr_key mapKeys(LogAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_log_attr_value mapValues(LogAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_body Body TYPE tokenbf_v1(32768, 3, 0) GRANULARITY 1 +) ENGINE = MergeTree() +PARTITION BY toDate(Timestamp) +ORDER BY (ServiceName, SeverityText, toUnixTimestamp(Timestamp), TraceId) +TTL toDateTime(Timestamp) + toIntervalDay(3) +SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1; + +CREATE TABLE IF NOT EXISTS otel.otel_traces ( + Timestamp DateTime64(9) CODEC(Delta, ZSTD(1)), + TraceId String CODEC(ZSTD(1)), + SpanId String CODEC(ZSTD(1)), + ParentSpanId String CODEC(ZSTD(1)), + TraceState String CODEC(ZSTD(1)), + SpanName LowCardinality(String) CODEC(ZSTD(1)), + SpanKind LowCardinality(String) CODEC(ZSTD(1)), + ServiceName LowCardinality(String) CODEC(ZSTD(1)), + ResourceAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ScopeName String CODEC(ZSTD(1)), + ScopeVersion String CODEC(ZSTD(1)), + SpanAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + Duration Int64 CODEC(ZSTD(1)), + StatusCode LowCardinality(String) CODEC(ZSTD(1)), + StatusMessage String CODEC(ZSTD(1)), + Events Nested ( + Timestamp DateTime64(9), + Name LowCardinality(String), + Attributes Map(LowCardinality(String), String) + ) CODEC(ZSTD(1)), + Links Nested ( + TraceId String, + SpanId String, + TraceState String, + Attributes Map(LowCardinality(String), String) + ) CODEC(ZSTD(1)), + INDEX idx_trace_id TraceId TYPE bloom_filter(0.001) GRANULARITY 1, + INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_span_attr_key mapKeys(SpanAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_span_attr_value mapValues(SpanAttributes) TYPE bloom_filter(0.01) GRANULARITY 1 +) ENGINE = MergeTree() +PARTITION BY toDate(Timestamp) +ORDER BY (ServiceName, SpanName, toUnixTimestamp(Timestamp), TraceId) +TTL toDateTime(Timestamp) + toIntervalDay(7) +SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1; + +CREATE TABLE IF NOT EXISTS otel.otel_metrics ( + ResourceAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ResourceSchemaUrl String CODEC(ZSTD(1)), + ScopeName String CODEC(ZSTD(1)), + ScopeVersion String CODEC(ZSTD(1)), + ScopeAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ScopeDroppedAttrCount UInt32 CODEC(ZSTD(1)), + ScopeSchemaUrl String CODEC(ZSTD(1)), + MetricName String CODEC(ZSTD(1)), + MetricDescription String CODEC(ZSTD(1)), + MetricUnit String CODEC(ZSTD(1)), + Attributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + StartTimeUnix DateTime64(9) CODEC(Delta, ZSTD(1)), + TimeUnix DateTime64(9) CODEC(Delta, ZSTD(1)), + Value Float64 CODEC(ZSTD(1)), + Flags UInt32 CODEC(ZSTD(1)), + Exemplars Nested ( + FilteredAttributes Map(LowCardinality(String), String), + TimeUnix DateTime64(9), + Value Float64, + SpanId String, + TraceId String + ) CODEC(ZSTD(1)), + AggTemp Int32 CODEC(ZSTD(1)), + IsMonotonic Bool CODEC(ZSTD(1)), + INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_key mapKeys(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_value mapValues(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_attr_key mapKeys(Attributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_attr_value mapValues(Attributes) TYPE bloom_filter(0.01) GRANULARITY 1 +) ENGINE = MergeTree() +PARTITION BY toDate(TimeUnix) +ORDER BY (MetricName, Attributes, toUnixTimestamp(TimeUnix)) +TTL toDateTime(TimeUnix) + toIntervalDay(30) +SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1; diff --git a/docker/dev/clickhouse/users.xml b/docker/dev/clickhouse/users.xml new file mode 100644 index 0000000000..743cada261 --- /dev/null +++ b/docker/dev/clickhouse/users.xml @@ -0,0 +1,35 @@ + + + + + default + + ::/0 + + default + default + 1 + + + + + + 10000000000 + 0 + random + + + + + + + 3600 + 0 + 0 + 0 + 0 + 0 + + + + diff --git a/docker/dev/docker-compose.yml b/docker/dev/docker-compose.yml new file mode 100644 index 0000000000..eaf6561792 --- /dev/null +++ b/docker/dev/docker-compose.yml @@ -0,0 +1,212 @@ +services: + clickhouse: + restart: unless-stopped + image: clickhouse/clickhouse-server:25.1.5 + volumes: + - clickhouse-data:/var/lib/clickhouse + - ./clickhouse/config.xml:/etc/clickhouse-server/config.d/config.xml + - ./clickhouse/users.xml:/etc/clickhouse-server/users.d/users.xml + - ./clickhouse/client-config.xml:/etc/clickhouse-client/config.xml + - ./clickhouse/init:/docker-entrypoint-initdb.d + environment: + - CLICKHOUSE_ALWAYS_RUN_INITDB_SCRIPTS=true + - CLICKHOUSE_USER=default + - CLICKHOUSE_PASSWORD=default + - CLICKHOUSE_HTTP_PORT=9300 + - CLICKHOUSE_TCP_PORT=9301 + networks: + - rivet-network-to-core + - rivet-core-network + healthcheck: + test: + - CMD + - clickhouse-client + - '--host' + - 127.0.0.1 + - '--port' + - '9301' + - '--user' + - system + - '--password' + - default + - '--query' + - SELECT 1 + interval: 2s + timeout: 10s + retries: 10 + grafana: + image: grafana/grafana:11.5.2 + volumes: + - grafana-data:/var/lib/grafana + - ./grafana/grafana.ini:/etc/grafana/grafana.ini + - ./grafana/provisioning:/etc/grafana/provisioning + - ./grafana/dashboards:/var/lib/grafana/dashboards + environment: + - GF_INSTALL_PLUGINS=grafana-clickhouse-datasource + ports: + - '3100:3000' + networks: + - rivet-core-network + depends_on: + clickhouse: + condition: service_healthy + postgres: + restart: unless-stopped + image: postgres:16-alpine + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=postgres + volumes: + - ./postgres/init-db.sh:/docker-entrypoint-initdb.d/init-db.sh + - postgres-data:/var/lib/postgresql/data + ports: + - '5432:5432' + healthcheck: + test: + - CMD-SHELL + - pg_isready -U postgres -d postgres + interval: 2s + timeout: 10s + retries: 10 + networks: + - rivet-network + rivet-shell: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: sleep infinity + stop_grace_period: 0s + depends_on: + postgres: + condition: service_healthy + volumes: + - ./rivet-engine/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network + - rivet-network-to-core + - rivet-network-engine-peer + vector-server: + restart: unless-stopped + image: timberio/vector:0.48.0-distroless-static + command: '-C /etc/vector' + volumes: + - vector-server-data-local:/var/lib/vector + - ./vector-server:/etc/vector + networks: + - rivet-network + - rivet-network-to-core + depends_on: + clickhouse: + condition: service_healthy + vector-client: + restart: unless-stopped + image: timberio/vector:0.48.0-distroless-static + command: '-C /etc/vector' + volumes: + - vector-client-data-local:/var/lib/vector + - ./vector-client:/etc/vector + networks: + - rivet-network + depends_on: + vector-server: + condition: service_started + otel-collector-server: + image: otel/opentelemetry-collector-contrib:latest + restart: unless-stopped + command: '--config=/etc/otel/config.yaml' + volumes: + - ./otel-collector-server/config.yaml:/etc/otel/config.yaml:ro + environment: + - CLICKHOUSE_PASSWORD=default + depends_on: + clickhouse: + condition: service_healthy + networks: + - rivet-network + - rivet-network-to-core + otel-collector-client: + image: otel/opentelemetry-collector-contrib:latest + restart: unless-stopped + command: '--config=/etc/otel/config.yaml' + volumes: + - ./otel-collector-client/config.yaml:/etc/otel/config.yaml:ro + depends_on: + otel-collector-server: + condition: service_started + networks: + - rivet-network + rivet-engine: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + platform: linux/amd64 + restart: unless-stopped + command: /usr/bin/rivet-engine start + environment: + - RUST_LOG_ANSI_COLOR=1 + - RIVET_OTEL_ENABLED=1 + - RIVET_OTEL_SAMPLER_RATIO=1 + - RIVET_OTEL_GRPC_ENDPOINT=http://otel-collector-client:4317 + stop_grace_period: 0s + depends_on: + vector-client: + condition: service_started + otel-collector-client: + condition: service_started + postgres: + condition: service_healthy + volumes: + - ./rivet-engine/config.jsonc:/etc/rivet/config.jsonc:ro + networks: + - rivet-network + - rivet-network-to-core + - rivet-network-engine-peer + ports: + - '6420:6420' + healthcheck: + test: + - CMD + - curl + - '-f' + - http://127.0.0.1:6421/health + interval: 2s + timeout: 10s + retries: 10 + start_period: 30s + runner: + build: + context: ../.. + dockerfile: sdks/typescript/test-runner/Dockerfile + platform: linux/amd64 + restart: unless-stopped + environment: + - RIVET_ENDPOINT=http://rivet-engine:6420 + - RUNNER_HOST=runner + stop_grace_period: 4s + ports: + - '5050:5050' + depends_on: + rivet-engine: + condition: service_healthy + networks: + - rivet-network +networks: + rivet-core-network: + driver: bridge + rivet-network: + driver: bridge + rivet-network-engine-peer: + driver: bridge + rivet-network-to-core: + driver: bridge +volumes: + clickhouse-data: null + grafana-data: null + postgres-data: null + vector-server-data-local: null + vector-client-data-local: null diff --git a/docker/dev/grafana/dashboards/api.json b/docker/dev/grafana/dashboards/api.json new file mode 100644 index 0000000000..34004bf134 --- /dev/null +++ b/docker/dev/grafana/dashboards/api.json @@ -0,0 +1,1172 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 7, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 24, + "panels": [], + "title": "API", + "type": "row" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 26, + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_api_request_duration'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Request Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 27, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_api_request_pending'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Requests Pending", + "transformations": [ + { + "id": "groupingToMatrix", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 10 + }, + "id": 32, + "interval": "15s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n sum(Sum) / sum(Count) as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nHAVING sum(Count) > 0\nORDER BY time", + "refId": "A" + } + ], + "title": "Duration (avg)", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 10 + }, + "id": 33, + "interval": "15s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label, bounds, idx\nORDER BY time", + "refId": "A" + } + ], + "title": "Duration (p95)", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "bounds" + } + }, + { + "id": "convertFieldType", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 16, + "y": 10 + }, + "id": 34, + "interval": "15s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n Attributes['method'] as method,\n Attributes['path'] as path,\n histogramQuantile(arrayZip(ExplicitBounds, BucketCounts), 0.99) as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND Attributes['watch'] = '0'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, method, path\nORDER BY time", + "refId": "A" + } + ], + "title": "Duration (p99)", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 19 + }, + "id": 25, + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n sum(Value) / $__interval_ms * 1000 as value\n -- (\n -- SELECT\n -- sum(Value) / $__interval_ms * 1000 as value\n -- FROM otel.otel_metrics_sum\n -- WHERE MetricName = 'rivet_api_request_total'\n -- AND $__conditionalAll(Attributes['path'], $path)\n -- AND $__conditionalAll(Attributes['method'], $method)\n -- AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n -- AND $__timeFilter(TimeUnix)\n -- ) as prev_value\n -- lagInFrame(value, 1, value) OVER (ORDER BY time) as previous_value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_api_request_total'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Request Rate", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 19 + }, + "id": 28, + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Name", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}: {{status}} ({{error_code}})", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path'], ': ',\n Attributes['status'], ' (',\n Attributes['error_code'], ')'\n ) as label,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_api_request_errors'\n AND Attributes['status'] LIKE '4%'\n AND Attributes['error_code'] NOT IN ('API_CANCELLED', 'CAPTCHA_CAPTCHA_REQUIRED')\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Error Rate (4xx)", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\label" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 16, + "y": 19 + }, + "id": 31, + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}: {{status}} ({{error_code}})", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path'], ': ',\n Attributes['error_code'], ' (',\n Attributes['status'], ')'\n ) as label,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_api_request_errors'\n AND Attributes['status'] LIKE '5%'\n AND Attributes['error_code']-- NOT IN ('API_CANCELLED', 'CAPTCHA_CAPTCHA_REQUIRED')\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Error Rate (5xx)", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "log": 2, + "type": "log" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "percent" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 28 + }, + "id": 35, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{method}} {{path}}: {{status}} {{error_code}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['method'] as method,\n Attributes['path'] as path,\n Attributes['status'] as status,\n Attributes['error_code'] as error_code,\n sum(Count) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND (Attributes['status'] = '200' OR Attributes['status'] LIKE '5%')\n AND Attributes['error_code']-- NOT IN ('API_CANCELLED', 'CAPTCHA_CAPTCHA_REQUIRED')\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, method, path, status, error_code\nORDER BY time", + "refId": "A" + } + ], + "title": "200 vs 5xx (4xx excluded)", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "30s", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request_errors' ORDER BY datacenter_id", + "includeAll": true, + "label": "Datacenter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request_errors' ORDER BY datacenter_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['path'] as path FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) ORDER BY path", + "includeAll": true, + "label": "Path", + "multi": true, + "name": "path", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['path'] as path FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) ORDER BY path", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['method'] as method FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) AND $__conditionalAll(Attributes['path'], $path) ORDER BY method", + "includeAll": true, + "label": "Method", + "multi": true, + "name": "method", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['method'] as method FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) AND $__conditionalAll(Attributes['path'], $path) ORDER BY method", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-24h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "API", + "uid": "feg8y72gpm2o0c", + "version": 1, + "weekStart": "" +} diff --git a/docker/dev/grafana/dashboards/cache.json b/docker/dev/grafana/dashboards/cache.json new file mode 100644 index 0000000000..5d762023ea --- /dev/null +++ b/docker/dev/grafana/dashboards/cache.json @@ -0,0 +1,1176 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 4, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 10, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n CASE\n WHEN ResourceAttributes['datacenter_id'] != '' AND ResourceAttributes['server_id'] != '' THEN concat(ResourceAttributes['datacenter_id'], ' - ', ResourceAttributes['server_id'])\n ELSE 'Route Cache Size'\n END as label,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_route_cache_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Route Cache Size", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\label" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 11, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_rate_limiter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Rate Limiters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 12, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_in_flight_counter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "In-Flight Counters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 8 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_tcp_connection_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active TCP Connections", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 8 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_tcp_connection'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "TCP Connection Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 8 + }, + "id": 1, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_tcp_connection_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "TCP Connection Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 16 + }, + "id": 7, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_proxy_request_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Proxy Requests", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 16 + }, + "id": 8, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_proxy_request'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Proxy Request Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 16 + }, + "id": 9, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_proxy_request_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Proxy Request Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 24 + }, + "id": 6, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_resolve_route_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Resolve Route Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "description": "", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "description": "", + "includeAll": true, + "label": "Dataceter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "description": "", + "includeAll": true, + "label": "Server ID", + "multi": true, + "name": "server_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Rivet Guard", + "uid": "cen785ige8fswd", + "version": 1, + "weekStart": "" +} diff --git a/docker/dev/grafana/dashboards/futures.json b/docker/dev/grafana/dashboards/futures.json new file mode 100644 index 0000000000..0c992c4bcb --- /dev/null +++ b/docker/dev/grafana/dashboards/futures.json @@ -0,0 +1,208 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_instrumented_future_duration'\n AND $__conditionalAll(Attributes['name'], $name)\n AND $__conditionalAll(Attributes['location'], $location)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Instrumented Future Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "30s", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['name'] as name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY name", + "includeAll": true, + "label": "Name", + "multi": true, + "name": "name", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['name'] as name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY name", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['location'] as location FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY location", + "includeAll": true, + "label": "Location", + "multi": true, + "name": "location", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['location'] as location FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY location", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Futures", + "version": 0, + "weekStart": "" +} \ No newline at end of file diff --git a/docker/dev/grafana/dashboards/gasoline.json b/docker/dev/grafana/dashboards/gasoline.json new file mode 100644 index 0000000000..bac8c7b6da --- /dev/null +++ b/docker/dev/grafana/dashboards/gasoline.json @@ -0,0 +1,2583 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": 3, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{workflow_name}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_active'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Running Workflows", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 3, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{workflow_name}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_sleeping'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Sleeping Workflows", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 1, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{workflow_name}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_dead'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Dead Workflows", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 6, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "({{workflow_name}}) {{error_code}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n Attributes['error_code'] as error_code,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_dead'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name, error_code\nORDER BY time", + "refId": "A" + } + ], + "title": "Dead Workflow Errors", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "__auto", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n count(*) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_worker_last_ping'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Workers", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "datacenter_id", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\datacenter_id" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 4, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{signal_name}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['signal_name'] as signal_name,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_signal_pending'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, signal_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Pending Signals", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "signal_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\signal_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 10, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size", + "value": "" + }, + "yBuckets": { + "mode": "size", + "scale": { + "log": 2, + "type": "log" + }, + "value": "" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "hide": false, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_signal_recv_lag'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Signal Receive Lag", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 24 + }, + "id": 11, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_signal_pull_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY\n Time, le\nORDER BY\n Time, le", + "refId": "A" + } + ], + "title": "Pull Signals Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 32 + }, + "id": 13, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "instant": false, + "legendFormat": "{{worker_instance_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['worker_instance_id'] as worker_instance_id,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_last_pull_workflows_duration'\n AND ResourceAttributes['cluster_id'] LIKE '${cluster_id:regex}'\n AND ResourceAttributes['datacenter_id'] LIKE '${datacenter_id:regex}'\n AND $__timeFilter(TimeUnix)\nGROUP BY time, worker_instance_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Last Pull Workflows Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "worker_instance_id", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\worker_instance_id" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 32 + }, + "id": 14, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "instant": false, + "legendFormat": "{{worker_instance_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['worker_instance_id'] as worker_instance_id,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_last_pull_workflows_history_duration'\n AND ResourceAttributes['cluster_id'] LIKE '${cluster_id:regex}'\n AND ResourceAttributes['datacenter_id'] LIKE '${datacenter_id:regex}'\n AND $__timeFilter(TimeUnix)\nGROUP BY time, worker_instance_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Last Pull Workflows History Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "worker_instance_id", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\worker_instance_id" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 40 + }, + "id": 23, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_pull_workflows_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Pull Workflows Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 40 + }, + "id": 24, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_pull_workflows_history_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Pull Workflows History Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 48 + }, + "id": 16, + "panels": [], + "title": "Steps", + "type": "row" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 49 + }, + "id": 12, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_activity_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Activity Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 49 + }, + "id": 9, + "interval": "15s", + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{activity_name}}: {{error_code}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['activity_name'] as activity_name,\n Attributes['error_code'] as error_code,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_gasoline_activity_errors'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, activity_name, error_code\nORDER BY time", + "refId": "A" + } + ], + "title": "Activity Error Rate", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "activity_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\activity_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 58 + }, + "id": 21, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_loop_iteration_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Loop Upsert Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ev/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 58 + }, + "id": 25, + "interval": "15s", + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "legendFormat": "{{workflow_name}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n sum(Count) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_gasoline_loop_iteration_duration'\n AND Attributes['workflow_name'] LIKE '${workflow_name:regex}'\n AND ResourceAttributes['cluster_id'] LIKE '${cluster_id:regex}'\n AND ResourceAttributes['datacenter_id'] LIKE '${datacenter_id:regex}'\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Loop Events Per Second", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 67 + }, + "id": 17, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_message_send_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Message Send Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 67 + }, + "id": 20, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_signal_send_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Signal Send Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 76 + }, + "id": 22, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_find_workflows_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Find Workflows Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 76 + }, + "id": 19, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_workflow_dispatch_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Sub Workflow Dispatch Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "5s", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY cluster_id", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY cluster_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY datacenter_id", + "includeAll": true, + "label": "Datacenter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY datacenter_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['workflow_name'] as workflow_name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_gasoline_signal_recv_lag' ORDER BY workflow_name", + "includeAll": true, + "label": "Workflow Name", + "multi": true, + "name": "workflow_name", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['workflow_name'] as workflow_name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_gasoline_signal_recv_lag' ORDER BY workflow_name", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Gasoline", + "uid": "636d22f9-d18f-4086-8b45-7c50886a105c", + "version": 1, + "weekStart": "" +} diff --git a/docker/dev/grafana/dashboards/guard.json b/docker/dev/grafana/dashboards/guard.json new file mode 100644 index 0000000000..fb657d441b --- /dev/null +++ b/docker/dev/grafana/dashboards/guard.json @@ -0,0 +1,1150 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 115, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 10, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_route_cache_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Route Cache Size", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 11, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_rate_limiter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Rate Limiters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 12, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_in_flight_counter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "In-Flight Counters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 8 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_tcp_connection_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active TCP Connections", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 8 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_tcp_connection'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "TCP Connection Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 8 + }, + "id": 1, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_tcp_connection_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "TCP Connection Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 16 + }, + "id": 7, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_proxy_request_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Proxy Requests", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 16 + }, + "id": 8, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_proxy_request'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Proxy Request Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 16 + }, + "id": 9, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_proxy_request_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Proxy Request Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 24 + }, + "id": 6, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_resolve_route_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Resolve Route Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "description": "", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "description": "", + "includeAll": true, + "label": "Dataceter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "description": "", + "includeAll": true, + "label": "Server ID", + "multi": true, + "name": "server_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Rivet Guard", + "uid": "cen785ige8fswd", + "version": 1, + "weekStart": "" +} diff --git a/docker/dev/grafana/dashboards/tokio.json b/docker/dev/grafana/dashboards/tokio.json new file mode 100644 index 0000000000..efa5e4b49f --- /dev/null +++ b/docker/dev/grafana/dashboards/tokio.json @@ -0,0 +1,1009 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": 81, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 24, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_global_queue_depth'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Global Queue Depth", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 27, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_worker_local_queue_depth'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Worker Queue Depth", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 11, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_tokio_task_poll_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Task Poll Times", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 26, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_worker_overflow_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Worker Overflow Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 23, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_future_schedule_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Future Schedule Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 25, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_thread_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Thread Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "tasks/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 28, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_tokio_task'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Task Spawn Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 24 + }, + "id": 29, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_active_task_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Tasks", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "5s", + "schemaVersion": 40, + "templating": { + "list": [ + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY cluster_id", + "description": "", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY cluster_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY datacenter_id", + "description": "", + "includeAll": true, + "label": "Dataceter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY datacenter_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY server_id", + "description": "", + "includeAll": true, + "label": "Server ID", + "multi": true, + "name": "server_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY server_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['pool_type'] as pool_type FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY pool_type", + "includeAll": true, + "label": "Pool", + "multi": true, + "name": "pool_type", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['pool_type'] as pool_type FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY pool_type", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Tokio", + "uid": "636d22f9-d18f-4086-8b45-7c50886a105d", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/docker/dev/grafana/dashboards/traces.json b/docker/dev/grafana/dashboards/traces.json new file mode 100644 index 0000000000..64f6b552c9 --- /dev/null +++ b/docker/dev/grafana/dashboards/traces.json @@ -0,0 +1,979 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 21, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 9, + "panels": [], + "title": "Traces", + "type": "row" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "bars", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 0, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 1 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-traces" + }, + "editorType": "sql", + "format": 0, + "meta": { + "builderOptions": { + "aggregates": [ + { + "aggregateType": "count", + "column": "" + } + ], + "columns": [ + { + "hint": "time", + "name": "Timestamp", + "type": "DateTime64(9)" + } + ], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "hint": "time", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "ServiceName" + ], + "limit": 10000, + "mode": "trend", + "orderBy": [], + "queryType": "timeseries", + "table": "otel_traces" + } + }, + "pluginVersion": "4.0.6", + "queryType": "timeseries", + "rawSql": "SELECT\r\n $__timeInterval(Timestamp) as time,\r\n ServiceName,\r\n count() as ` `\r\nFROM otel.otel_traces\r\nWHERE\r\n ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )\r\n AND $__conditionalAll(ServiceName, $service_name)\r\n AND $__conditionalAll(SpanName, $span_name)\r\n AND (($ray_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['ray_id'], $ray_id))\r\n AND (($workflow_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['workflow_id'], $workflow_id))\r\nGROUP BY ServiceName, time\r\nORDER BY time ASC\r\nLIMIT 100000\r\n", + "refId": "A" + } + ], + "title": "Traces per Service", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Trace ID" + }, + "properties": [ + { + "id": "custom.width", + "value": 77 + }, + { + "id": "links", + "value": [ + { + "title": "__value.raw", + "url": "/d/8klBUGfVk/otel-traces?${__url_time_range}&${service_name:queryparam}&var-trace_id=${__value.raw}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Service Name" + }, + "properties": [ + { + "id": "custom.width", + "value": 130 + }, + { + "id": "links", + "value": [ + { + "title": "__value.raw", + "url": "/d/8klBUGfVk/otel-traces?${__url_time_range}&${trace_id:queryparam}&var-serviceName=${__value.raw}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Duration" + }, + "properties": [ + { + "id": "unit", + "value": "ms" + }, + { + "id": "custom.cellOptions", + "value": { + "mode": "lcd", + "type": "gauge", + "valueDisplayMode": "text" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "timestamp" + }, + "properties": [ + { + "id": "custom.width", + "value": 216 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Service Tags" + }, + "properties": [ + { + "id": "custom.inspect", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "timestamp" + }, + "properties": [ + { + "id": "custom.width", + "value": 248 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "timestamp" + }, + "properties": [ + { + "id": "custom.width", + "value": 234 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": " " + }, + "properties": [ + { + "id": "custom.width", + "value": 49 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Span Name" + }, + "properties": [ + { + "id": "custom.width", + "value": 140 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Ts" + }, + "properties": [ + { + "id": "custom.width", + "value": 168 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "URI/workflow_id/actor_id" + }, + "properties": [ + { + "id": "custom.width", + "value": 920 + } + ] + } + ] + }, + "gridPos": { + "h": 13, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 4, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Duration" + } + ] + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorType": "sql", + "format": 1, + "meta": { + "builderOptions": { + "columns": [], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "queryType": "table", + "table": "otel_traces" + } + }, + "pluginVersion": "4.9.0", + "queryType": "table", + "rawSql": "SELECT\r\n (argMin(StatusCode, Timestamp) = 'Error' ? '⚠️' : '') as ` `,\r\n min(Timestamp) as Ts,\r\n TraceId as `Trace ID`,\r\n argMin(ServiceName, Timestamp) as `Service Name`,\r\n argMin(SpanName, Timestamp) as `Span Name`,\r\n argMin(coalesce(NULLIF(SpanAttributes['uri'], ''), NULLIF(SpanAttributes['workflow_id'], ''), SpanAttributes['actor_id']), Timestamp) as `URI/workflow_id/actor_id`,\r\n divide(max(Duration), 1000000) as Duration\r\nFROM otel.otel_traces\r\nWHERE\r\n $__conditionalAll(ServiceName, $service_name)\r\n AND $__conditionalAll(SpanName, $span_name)\r\n AND (($ray_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['ray_id'], $ray_id))\r\n AND (($workflow_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['workflow_id'], $workflow_id))\r\n AND ServiceName != 'loadgenerator'\r\n AND ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )\r\nGROUP BY TraceId\r\nORDER BY Duration DESC\r\nLIMIT 100\r\n", + "refId": "A" + } + ], + "title": "Traces", + "type": "table" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, + "gridPos": { + "h": 17, + "w": 24, + "x": 0, + "y": 23 + }, + "id": 6, + "options": { + "spanFilters": { + "criticalPathOnly": false, + "matchesOnly": false, + "serviceNameOperator": "=", + "spanNameOperator": "=" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "builderOptions": { + "columns": [ + { + "hint": "trace_id", + "name": "TraceId" + }, + { + "hint": "trace_span_id", + "name": "SpanId" + }, + { + "hint": "trace_parent_span_id", + "name": "ParentSpanId" + }, + { + "hint": "trace_service_name", + "name": "ServiceName" + }, + { + "hint": "trace_operation_name", + "name": "SpanName" + }, + { + "hint": "time", + "name": "Timestamp" + }, + { + "hint": "trace_duration_time", + "name": "Duration" + }, + { + "hint": "trace_tags", + "name": "SpanAttributes" + }, + { + "hint": "trace_service_tags", + "name": "ResourceAttributes" + }, + { + "hint": "trace_status_code", + "name": "StatusCode" + } + ], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "hint": "time", + "key": "", + "operator": "WITH IN DASHBOARD TIME RANGE", + "type": "datetime" + }, + { + "condition": "AND", + "filterType": "custom", + "hint": "trace_duration_time", + "key": "", + "operator": ">", + "type": "UInt64", + "value": 0 + }, + { + "condition": "AND", + "filterType": "custom", + "hint": "trace_service_name", + "key": "", + "operator": "IS ANYTHING", + "type": "string", + "value": "" + } + ], + "limit": 1000, + "meta": { + "isTraceIdMode": true, + "otelEnabled": true, + "otelVersion": "latest", + "traceDurationUnit": "nanoseconds", + "traceId": "${trace_id}" + }, + "mode": "list", + "orderBy": [ + { + "default": true, + "dir": "DESC", + "hint": "time", + "name": "" + }, + { + "default": true, + "dir": "DESC", + "hint": "trace_duration_time", + "name": "" + } + ], + "queryType": "traces", + "table": "otel_traces" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-traces" + }, + "editorType": "builder", + "format": 3, + "meta": { + "builderOptions": { + "columns": [], + "database": "", + "limit": 100, + "mode": "list", + "queryType": "table", + "table": "" + } + }, + "pluginVersion": "4.0.6", + "queryType": "traces", + "rawSql": "WITH\n\t(SELECT min(Start) FROM otel.otel_traces_trace_id_ts WHERE $__conditionalAll(TraceId, $trace_id)) as trace_start,\n\t(SELECT max(End) + 1 FROM otel.otel_traces_trace_id_ts WHERE $__conditionalAll(TraceId, $trace_id)) as trace_end\nSELECT\n\tTraceId as traceID,\n\tSpanId as spanID,\n\tParentSpanId as parentSpanID,\n\tServiceName as serviceName,\n\tSpanName as operationName, Timestamp as startTime,\n\tmultiply(Duration, 0.000001) as duration,\n\tarrayMap(key -> map('key', key, 'value', SpanAttributes[key]), mapKeys(SpanAttributes)) as tags,\n\tarrayMap(key -> map('key', key, 'value', ResourceAttributes[key]), mapKeys(ResourceAttributes)) as serviceTags,\n\tarrayMap((name, timestamp, attributes) -> tuple(name, toString(multiply(toUnixTimestamp64Nano(timestamp), 0.000001)), arrayMap( key -> map('key', key, 'value', attributes[key]), mapKeys(attributes)))::Tuple(name String, timestamp String, fields Array(Map(String, String))), `Events.Name`, `Events.Timestamp`, `Events.Attributes`) AS logs,\n\tarrayMap((traceID, spanID, attributes) -> tuple(traceID, spanID, arrayMap(key -> map('key', key, 'value', attributes[key]), mapKeys(attributes)))::Tuple(traceID String, spanID String, tags Array(Map(String, String))), `Links.TraceId`, `Links.SpanId`, `Links.Attributes`) AS references\nFROM otel.otel_traces\nWHERE\n\t$__conditionalAll(traceID, $trace_id) AND startTime >= trace_start AND startTime <= trace_end AND ( Duration > 0 )\nORDER BY Timestamp DESC, Duration DESC\nLIMIT 1000", + "refId": "A" + } + ], + "title": "Trace Details", + "type": "traces" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "bars", + "fillOpacity": 24, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 8, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-traces" + }, + "editorType": "sql", + "format": 0, + "meta": { + "builderOptions": { + "aggregates": [ + { + "aggregateType": "count", + "column": "" + } + ], + "columns": [ + { + "hint": "time", + "name": "Timestamp", + "type": "DateTime64(9)" + } + ], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "hint": "time", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "ServiceName" + ], + "limit": 10000, + "mode": "trend", + "orderBy": [], + "queryType": "timeseries", + "table": "otel_traces" + } + }, + "pluginVersion": "4.0.6", + "queryType": "timeseries", + "rawSql": "SELECT\r\n $__timeInterval(Timestamp) as time,\r\n count(*) as ` `,\r\n ServiceName\r\nFROM otel.otel_traces\r\nWHERE\r\n $__conditionalAll(TraceId, $trace_id)\r\n AND ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )\r\n AND $__conditionalAll(ServiceName, $service_name)\r\n AND $__conditionalAll(SpanName, $span_name)\r\n AND (($ray_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['ray_id'], $ray_id)\r\n AND (($workflow_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['workflow_id'], $workflow_id))\r\n AND StatusCode IN ('Error', 'STATUS_CODE_ERROR')\r\n AND ServiceName != 'loadgenerator' GROUP BY ServiceName, time\r\nORDER BY time ASC\r\nLIMIT 100000", + "refId": "A" + } + ], + "title": "Error rates", + "type": "timeseries" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 49 + }, + "id": 10, + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 61 + }, + "id": 11, + "options": { + "dedupStrategy": "none", + "enableInfiniteScrolling": false, + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": true, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "builderOptions": { + "columns": [ + { + "hint": "time", + "name": "Timestamp", + "type": "DateTime64(9)" + }, + { + "hint": "log_level", + "name": "SeverityText", + "type": "LowCardinality(String)" + }, + { + "hint": "log_message", + "name": "Body", + "type": "String" + } + ], + "database": "otel", + "filters": [], + "limit": 1000, + "meta": { + "logMessageLike": "", + "otelVersion": "latest" + }, + "mode": "list", + "orderBy": [], + "queryType": "logs", + "table": "otel_logs" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorType": "builder", + "format": 2, + "pluginVersion": "4.0.6", + "rawSql": "SELECT Timestamp as timestamp, Body as body, SeverityText as level FROM \"otel\".\"otel_logs\" LIMIT 1000", + "refId": "A" + } + ], + "title": "Trace Logs", + "type": "logs" + } + ], + "title": "Logs", + "type": "row" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "ClickHouse", + "value": "ClickHouse" + }, + "includeAll": false, + "label": "ClickHouse instance", + "name": "datasource", + "options": [], + "query": "grafana-clickhouse-datasource", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ServiceName FROM otel.otel_traces", + "includeAll": true, + "label": "Service Name", + "multi": true, + "name": "service_name", + "options": [], + "query": "SELECT DISTINCT ServiceName FROM otel.otel_traces", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT TraceId FROM otel.otel_traces WHERE ParentSpanId = '' LIMIT 100", + "includeAll": true, + "label": "Trace ID", + "name": "trace_id", + "options": [], + "query": "SELECT DISTINCT TraceId FROM otel.otel_traces WHERE ParentSpanId = '' LIMIT 100", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT SpanName FROM otel.otel_traces WHERE $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "description": "", + "includeAll": true, + "label": "Span", + "multi": true, + "name": "span_name", + "options": [], + "query": "SELECT DISTINCT SpanName FROM otel.otel_traces WHERE $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "allValue": "'All'", + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT SpanAttributes['ray_id'] FROM otel.otel_traces WHERE SpanAttributes['ray_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "description": "", + "includeAll": true, + "label": "Ray ID", + "multi": true, + "name": "ray_id", + "options": [], + "query": "SELECT DISTINCT SpanAttributes['ray_id'] FROM otel.otel_traces WHERE SpanAttributes['ray_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "allValue": "'All'", + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT SpanAttributes['workflow_id'] FROM otel.otel_traces WHERE SpanAttributes['workflow_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "description": "", + "includeAll": true, + "label": "Workflow ID", + "multi": true, + "name": "workflow_id", + "options": [], + "query": "SELECT DISTINCT SpanAttributes['workflow_id'] FROM otel.otel_traces WHERE SpanAttributes['workflow_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "America/Los_Angeles", + "title": "Traces", + "uid": "8klBUGfVk", + "version": 2, + "weekStart": "" +} diff --git a/docker/dev/grafana/grafana.ini b/docker/dev/grafana/grafana.ini new file mode 100644 index 0000000000..1bd9bfe697 --- /dev/null +++ b/docker/dev/grafana/grafana.ini @@ -0,0 +1,14 @@ +[server] +http_port = 3000 +root_url = http://localhost:3100 + +[security] +admin_user = admin +admin_password = admin + +[auth.anonymous] +enabled = true +org_role = Viewer + +[dashboards] +default_home_dashboard_path = /var/lib/grafana/dashboards/api.json diff --git a/docker/dev/grafana/provisioning/dashboards/dashboards.yaml b/docker/dev/grafana/provisioning/dashboards/dashboards.yaml new file mode 100644 index 0000000000..7d91589dc7 --- /dev/null +++ b/docker/dev/grafana/provisioning/dashboards/dashboards.yaml @@ -0,0 +1,10 @@ +apiVersion: 1 +providers: + - name: rivet-dashboards + orgId: 1 + folder: '' + type: file + disableDeletion: false + updateIntervalSeconds: 10 + options: + path: /var/lib/grafana/dashboards diff --git a/docker/dev/grafana/provisioning/datasources/datasources.yaml b/docker/dev/grafana/provisioning/datasources/datasources.yaml new file mode 100644 index 0000000000..f66d3bf036 --- /dev/null +++ b/docker/dev/grafana/provisioning/datasources/datasources.yaml @@ -0,0 +1,30 @@ +apiVersion: 1 +datasources: + - name: ClickHouse + uid: clickhouse + type: grafana-clickhouse-datasource + access: proxy + secureJsonData: + password: default + jsonData: + version: 2.0.0 + host: clickhouse + port: 9300 + defaultDatabase: default + protocol: http + secure: false + username: default + validateSql: true + logs: + otelEnabled: true + otelVersion: 1.2.9 + defaultDatabase: otel + defaultTable: otel_logs + timeColumn: TimestampTime + messageColumn: Body + levelColumn: SeverityText + traces: + otelEnabled: true + otelVersion: 1.2.9 + defaultDatabase: otel + defaultTable: otel_traces diff --git a/docker/dev/otel-collector-client/config.yaml b/docker/dev/otel-collector-client/config.yaml new file mode 100644 index 0000000000..6e963d5edf --- /dev/null +++ b/docker/dev/otel-collector-client/config.yaml @@ -0,0 +1,39 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + http: + endpoint: 0.0.0.0:4318 +processors: + batch: + timeout: 5s + send_batch_size: 10000 +exporters: + otlp/server: + endpoint: otel-collector-server:4317 + tls: + insecure: true +service: + pipelines: + logs: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server + traces: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server + metrics: + receivers: + - otlp + processors: + - batch + exporters: + - otlp/server diff --git a/docker/dev/otel-collector-server/config.yaml b/docker/dev/otel-collector-server/config.yaml new file mode 100644 index 0000000000..a74179019e --- /dev/null +++ b/docker/dev/otel-collector-server/config.yaml @@ -0,0 +1,61 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 +processors: + batch: + timeout: 5s + send_batch_size: 10000 +exporters: + clickhouse: + endpoint: http://clickhouse:9300 + database: otel + username: default + password: ${env:CLICKHOUSE_PASSWORD} + async_insert: true + ttl: 72h + compress: lz4 + create_schema: true + logs_table_name: otel_logs + traces_table_name: otel_traces + timeout: 5s + metrics_tables: + gauge: + name: otel_metrics_gauge + sum: + name: otel_metrics_sum + summary: + name: otel_metrics_summary + histogram: + name: otel_metrics_histogram + exponential_histogram: + name: otel_metrics_exp_histogram + retry_on_failure: + enabled: true + initial_interval: 5s + max_interval: 30s + max_elapsed_time: 300s +service: + pipelines: + logs: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse + traces: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse + metrics: + receivers: + - otlp + processors: + - batch + exporters: + - clickhouse diff --git a/docker/dev/postgres/init-db.sh b/docker/dev/postgres/init-db.sh new file mode 100755 index 0000000000..6b57fcfef7 --- /dev/null +++ b/docker/dev/postgres/init-db.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -e + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + CREATE DATABASE rivet_engine; +EOSQL diff --git a/docker/dev/rivet-engine/config.jsonc b/docker/dev/rivet-engine/config.jsonc new file mode 100644 index 0000000000..ba8f2b4dea --- /dev/null +++ b/docker/dev/rivet-engine/config.jsonc @@ -0,0 +1,56 @@ +{ + "guard": { + "port": 6420 + }, + "api_public": { + "lan_host": "rivet-engine", + "host": "0.0.0.0", + "port": 6421 + }, + "api_peer": { + "host": "0.0.0.0", + "port": 6422 + }, + "pegboard": { + "lan_host": "rivet-engine", + "host": "0.0.0.0", + "port": 6423 + }, + "logs": {}, + "topology": { + "datacenter_label": 1, + "datacenters": [ + { + "name": "local", + "datacenter_label": 1, + "is_leader": true, + "api_peer_url": "http://rivet-engine:6422", + "guard_url": "http://rivet-engine:6420" + } + ] + }, + "postgres": { + "url": "postgresql://postgres:postgres@postgres:5432/rivet_engine" + }, + "cache": { + "driver": "in_memory" + }, + "clickhouse": { + "http_url": "http://clickhouse:9300", + "native_url": "http://clickhouse:9301", + "username": "system", + "password": "default", + "provision_users": { + "vector": { + "username": "vector", + "password": "vector", + "role": "write" + } + }, + "secure": false + }, + "vector_http": { + "host": "vector-client", + "port": 5022 + } +} \ No newline at end of file diff --git a/docker/dev/vector-client/vector.yaml b/docker/dev/vector-client/vector.yaml new file mode 100644 index 0000000000..a4ca8e5da5 --- /dev/null +++ b/docker/dev/vector-client/vector.yaml @@ -0,0 +1,31 @@ +# Vector Client Configuration for Datacenter: local +# This Vector instance runs on each server to collect local logs and forward them +# to the central Vector server aggregator. + +api: + enabled: true + address: 0.0.0.0:8686 +sources: + http_events: + type: http_server + address: 0.0.0.0:5022 + encoding: ndjson +transforms: {} +sinks: + vector_server: + type: vector + inputs: + - http_events + address: vector-server:6000 + version: '2' + buffer: + type: disk + max_size: 2147483648 + when_full: block + console_debug: + type: console + inputs: + - http_events + encoding: + codec: json + \ No newline at end of file diff --git a/docker/dev/vector-server/vector.yaml b/docker/dev/vector-server/vector.yaml new file mode 100644 index 0000000000..5dfdbff2f5 --- /dev/null +++ b/docker/dev/vector-server/vector.yaml @@ -0,0 +1,61 @@ +# Vector Server (Aggregator) Configuration +# This Vector instance acts as an aggregator that collects logs and metrics from all Vector clients +# across different datacenters and forwards them to ClickHouse and other sinks. + +api: + enabled: true + address: 0.0.0.0:8686 +sources: + vector: + type: vector + address: 0.0.0.0:6000 + version: '2' + tcp_json: + type: socket + mode: tcp + address: 0.0.0.0:6100 + decoding: + codec: json + http_json: + type: http_server + address: 0.0.0.0:6200 + encoding: json + vector_metrics: + type: internal_metrics + vector_logs: + type: internal_logs +transforms: + clickhouse_dynamic_events_filter: + type: filter + inputs: + - vector + condition: + type: vrl + source: .source == "clickhouse" + clickhouse_dynamic_events_transform: + type: remap + inputs: + - clickhouse_dynamic_events_filter + source: "# Extract and store metadata\n__database = .database\n__table = .table\n__columns = .columns\n\n# Create a new object with just the columns data\n. = {\n\t\"__database\": __database,\n\t\"__table\": __table,\n\t# By default insert namespace column since most tables include this\n\t\"namespace\": \"rivet\"\n}\n\t\n# Merge in the column data that should be inserted\n. = merge!(., __columns)\n" +sinks: + clickhouse_dynamic_events: + type: clickhouse + inputs: + - clickhouse_dynamic_events_transform + endpoint: http://clickhouse:9300 + database: '{{ __database }}' + table: '{{ __table }}' + compression: gzip + auth: + strategy: basic + user: system + password: default + batch: + max_events: 1000 + timeout_secs: 10 + console_vector_logs: + type: console + inputs: + - vector_logs + encoding: + codec: json diff --git a/docker/toolchain/build.sh b/docker/engine/build.sh similarity index 78% rename from docker/toolchain/build.sh rename to docker/engine/build.sh index 29c602f852..6aa2491ab7 100755 --- a/docker/toolchain/build.sh +++ b/docker/engine/build.sh @@ -9,31 +9,31 @@ case $TARGET in echo "Building for Linux x86_64 platform" DOCKERFILE="linux-x86_64.Dockerfile" TARGET_STAGE="x86_64-builder" - BINARY="rivet-$TARGET" + BINARY="rivet-engine-$TARGET" ;; aarch64-unknown-linux-musl) echo "Building for Linux ARM64 platform" DOCKERFILE="linux-aarch64.Dockerfile" TARGET_STAGE="aarch64-builder" - BINARY="rivet-$TARGET" + BINARY="rivet-engine-$TARGET" ;; aarch64-apple-darwin) echo "Building for macOS ARM64 platform" DOCKERFILE="macos-aarch64.Dockerfile" TARGET_STAGE="aarch64-builder" - BINARY="rivet-$TARGET" + BINARY="rivet-engine-$TARGET" ;; x86_64-apple-darwin) echo "Building for macOS x86_64 platform" DOCKERFILE="macos-x86_64.Dockerfile" TARGET_STAGE="x86_64-builder" - BINARY="rivet-$TARGET" + BINARY="rivet-engine-$TARGET" ;; x86_64-pc-windows-gnu) echo "Building for Windows platform" DOCKERFILE="windows.Dockerfile" TARGET_STAGE="" # No target stage for Windows - BINARY="rivet-$TARGET.exe" + BINARY="rivet-engine-$TARGET.exe" ;; *) echo "Unsupported target: $TARGET" @@ -43,13 +43,13 @@ esac # Build docker image with target stage (if specified) if [ -n "$TARGET_STAGE" ]; then - DOCKER_BUILDKIT=1 docker build --target $TARGET_STAGE -f docker/toolchain/$DOCKERFILE -t rivet-cli-builder-$TARGET . + DOCKER_BUILDKIT=1 docker build --target $TARGET_STAGE -f docker/engine/$DOCKERFILE -t rivet-engine-builder-$TARGET . else - DOCKER_BUILDKIT=1 docker build -f docker/toolchain/$DOCKERFILE -t rivet-cli-builder-$TARGET . + DOCKER_BUILDKIT=1 docker build -f docker/engine/$DOCKERFILE -t rivet-engine-builder-$TARGET . fi # Extract binary -CONTAINER_ID=$(docker create rivet-cli-builder-$TARGET) +CONTAINER_ID=$(docker create rivet-engine-builder-$TARGET) mkdir -p dist docker cp "$CONTAINER_ID:/artifacts/$BINARY" dist/ docker rm "$CONTAINER_ID" diff --git a/docker/engine/linux-aarch64.Dockerfile b/docker/engine/linux-aarch64.Dockerfile new file mode 100644 index 0000000000..67e58d45b9 --- /dev/null +++ b/docker/engine/linux-aarch64.Dockerfile @@ -0,0 +1,72 @@ +# syntax=docker/dockerfile:1.4 +FROM rust:1.88.0 AS base +# Install dependencies +RUN apt-get update && apt-get install -y \ + musl-tools \ + musl-dev \ + llvm-14-dev \ + libclang-14-dev \ + clang-14 \ + libssl-dev \ + pkg-config \ + protobuf-compiler \ + ca-certificates \ + g++ \ + g++-multilib \ + git-lfs && \ + rm -rf /var/lib/apt/lists/* && \ + wget -q https://musl.cc/aarch64-linux-musl-cross.tgz && \ + tar -xzf aarch64-linux-musl-cross.tgz -C /opt/ && \ + rm aarch64-linux-musl-cross.tgz + +# Install musl targets +RUN rustup target add aarch64-unknown-linux-musl + +# Set environment variables +ENV PATH="/opt/aarch64-linux-musl-cross/bin:$PATH" \ + LIBCLANG_PATH=/usr/lib/llvm-14/lib \ + CLANG_PATH=/usr/bin/clang-14 \ + CC_aarch64_unknown_linux_musl=aarch64-linux-musl-gcc \ + CXX_aarch64_unknown_linux_musl=aarch64-linux-musl-g++ \ + AR_aarch64_unknown_linux_musl=aarch64-linux-musl-ar \ + CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=aarch64-linux-musl-gcc \ + CARGO_INCREMENTAL=0 \ + RUSTFLAGS="--cfg tokio_unstable -C target-feature=+crt-static -C link-arg=-static-libgcc" \ + CARGO_NET_GIT_FETCH_WITH_CLI=true + +# Set working directory +WORKDIR /build + +# Build for aarch64 +FROM base AS aarch64-builder + +# Set up OpenSSL for aarch64 musl target +ENV SSL_VER=1.1.1w +RUN wget https://www.openssl.org/source/openssl-$SSL_VER.tar.gz \ + && tar -xzf openssl-$SSL_VER.tar.gz \ + && cd openssl-$SSL_VER \ + && ./Configure no-shared no-async --prefix=/musl-aarch64 --openssldir=/musl-aarch64/ssl linux-aarch64 \ + && make -j$(nproc) \ + && make install_sw \ + && cd .. \ + && rm -rf openssl-$SSL_VER* + +# Configure OpenSSL env vars for the build +ENV OPENSSL_DIR=/musl-aarch64 \ + OPENSSL_INCLUDE_DIR=/musl-aarch64/include \ + OPENSSL_LIB_DIR=/musl-aarch64/lib \ + PKG_CONFIG_ALLOW_CROSS=1 + +# Copy the source code +COPY . . + +# Build for Linux with musl (static binary) - aarch64 +RUN --mount=type=cache,target=/usr/local/cargo/registry \ + --mount=type=cache,target=/usr/local/cargo/git \ + --mount=type=cache,target=/build/target \ + cargo build --bin rivet-engine --release --target aarch64-unknown-linux-musl -v && \ + mkdir -p /artifacts && \ + cp target/aarch64-unknown-linux-musl/release/rivet-engine /artifacts/rivet-engine-aarch64-unknown-linux-musl + +# Default command to show help +CMD ["ls", "-la", "/artifacts"] \ No newline at end of file diff --git a/docker/engine/linux-x86_64.Dockerfile b/docker/engine/linux-x86_64.Dockerfile new file mode 100644 index 0000000000..ec1389402f --- /dev/null +++ b/docker/engine/linux-x86_64.Dockerfile @@ -0,0 +1,73 @@ +# syntax=docker/dockerfile:1.4 +FROM rust:1.88.0 AS base + +# Install dependencies +RUN apt-get update && apt-get install -y \ + musl-tools \ + musl-dev \ + llvm-14-dev \ + libclang-14-dev \ + clang-14 \ + libssl-dev \ + pkg-config \ + protobuf-compiler \ + ca-certificates \ + g++ \ + g++-multilib \ + git-lfs && \ + rm -rf /var/lib/apt/lists/* && \ + wget -q https://musl.cc/x86_64-linux-musl-cross.tgz && \ + tar -xzf x86_64-linux-musl-cross.tgz -C /opt/ && \ + rm x86_64-linux-musl-cross.tgz + +# Install musl targets +RUN rustup target add x86_64-unknown-linux-musl + +# Set environment variables +ENV PATH="/opt/x86_64-linux-musl-cross/bin:$PATH" \ + LIBCLANG_PATH=/usr/lib/llvm-14/lib \ + CLANG_PATH=/usr/bin/clang-14 \ + CC_x86_64_unknown_linux_musl=x86_64-linux-musl-gcc \ + CXX_x86_64_unknown_linux_musl=x86_64-linux-musl-g++ \ + AR_x86_64_unknown_linux_musl=x86_64-linux-musl-ar \ + CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=x86_64-linux-musl-gcc \ + CARGO_INCREMENTAL=0 \ + RUSTFLAGS="--cfg tokio_unstable -C target-feature=+crt-static -C link-arg=-static-libgcc" \ + CARGO_NET_GIT_FETCH_WITH_CLI=true + +# Set working directory +WORKDIR /build + +# Build for x86_64 +FROM base AS x86_64-builder + +# Set up OpenSSL for x86_64 musl target +ENV SSL_VER=1.1.1w +RUN wget https://www.openssl.org/source/openssl-$SSL_VER.tar.gz \ + && tar -xzf openssl-$SSL_VER.tar.gz \ + && cd openssl-$SSL_VER \ + && ./Configure no-shared no-async --prefix=/musl --openssldir=/musl/ssl linux-x86_64 \ + && make -j$(nproc) \ + && make install_sw \ + && cd .. \ + && rm -rf openssl-$SSL_VER* + +# Configure OpenSSL env vars for the build +ENV OPENSSL_DIR=/musl \ + OPENSSL_INCLUDE_DIR=/musl/include \ + OPENSSL_LIB_DIR=/musl/lib \ + PKG_CONFIG_ALLOW_CROSS=1 + +# Copy the source code +COPY . . + +# Build for Linux with musl (static binary) - x86_64 +RUN --mount=type=cache,target=/usr/local/cargo/registry \ + --mount=type=cache,target=/usr/local/cargo/git \ + --mount=type=cache,target=/build/target \ + cargo build --bin rivet-engine --release --target x86_64-unknown-linux-musl -v && \ + mkdir -p /artifacts && \ + cp target/x86_64-unknown-linux-musl/release/rivet-engine /artifacts/rivet-engine-x86_64-unknown-linux-musl + +# Default command to show help +CMD ["ls", "-la", "/artifacts"] \ No newline at end of file diff --git a/docker/engine/macos-aarch64.Dockerfile b/docker/engine/macos-aarch64.Dockerfile new file mode 100644 index 0000000000..8c01e02e4a --- /dev/null +++ b/docker/engine/macos-aarch64.Dockerfile @@ -0,0 +1,73 @@ +# syntax=docker/dockerfile:1.4 +FROM rust:1.88.0 AS base + +# Install dependencies +RUN apt-get update && apt-get install -y \ + git-lfs \ + protobuf-compiler \ + clang \ + cmake \ + patch \ + libxml2-dev \ + wget \ + xz-utils \ + curl \ + && rm -rf /var/lib/apt/lists/* + +# Install osxcross +RUN git config --global --add safe.directory '*' && \ + git clone https://github.com/tpoechtrager/osxcross /root/osxcross && \ + cd /root/osxcross && \ + wget -nc https://github.com/phracker/MacOSX-SDKs/releases/download/11.3/MacOSX11.3.sdk.tar.xz && \ + mv MacOSX11.3.sdk.tar.xz tarballs/ && \ + UNATTENDED=yes OSX_VERSION_MIN=10.7 ./build.sh + +# Add osxcross to PATH +ENV PATH="/root/osxcross/target/bin:$PATH" + +# Tell Clang/bindgen to use the macOS SDK, and nudge Clang to prefer osxcross binutils. +ENV OSXCROSS_SDK=MacOSX11.3.sdk \ + SDKROOT=/root/osxcross/target/SDK/MacOSX11.3.sdk \ + BINDGEN_EXTRA_CLANG_ARGS_aarch64_apple_darwin="--sysroot=/root/osxcross/target/SDK/MacOSX11.3.sdk -isystem /root/osxcross/target/SDK/MacOSX11.3.sdk/usr/include" \ + CFLAGS_aarch64_apple_darwin="-B/root/osxcross/target/bin" \ + CXXFLAGS_aarch64_apple_darwin="-B/root/osxcross/target/bin" \ + CARGO_TARGET_AARCH64_APPLE_DARWIN_LINKER=aarch64-apple-darwin20.4-clang \ + CC_aarch64_apple_darwin=aarch64-apple-darwin20.4-clang \ + CXX_aarch64_apple_darwin=aarch64-apple-darwin20.4-clang++ \ + AR_aarch64_apple_darwin=aarch64-apple-darwin20.4-ar \ + RANLIB_aarch64_apple_darwin=aarch64-apple-darwin20.4-ranlib \ + MACOSX_DEPLOYMENT_TARGET=10.14 \ + RUSTFLAGS="--cfg tokio_unstable" \ + CARGO_INCREMENTAL=0 \ + CARGO_NET_GIT_FETCH_WITH_CLI=true + +# Set working directory +WORKDIR /build + +# Build for ARM64 macOS +FROM base AS aarch64-builder + +# Install macOS ARM64 target +RUN rustup target add aarch64-apple-darwin + +# Configure Cargo for cross-compilation (ARM64) +RUN mkdir -p /root/.cargo && \ + echo '\ +[target.aarch64-apple-darwin]\n\ +linker = "aarch64-apple-darwin20.4-clang"\n\ +ar = "aarch64-apple-darwin20.4-ar"\n\ +' > /root/.cargo/config.toml + +# Copy the source code +COPY . . + +# Build for ARM64 macOS +RUN --mount=type=cache,target=/usr/local/cargo/registry \ + --mount=type=cache,target=/usr/local/cargo/git \ + --mount=type=cache,target=/build/target \ + cargo build --bin rivet-engine --release --target aarch64-apple-darwin && \ + mkdir -p /artifacts && \ + cp target/aarch64-apple-darwin/release/rivet-engine /artifacts/rivet-engine-aarch64-apple-darwin + +# Default command to show help +CMD ["ls", "-la", "/artifacts"] diff --git a/docker/engine/macos-x86_64.Dockerfile b/docker/engine/macos-x86_64.Dockerfile new file mode 100644 index 0000000000..6911656199 --- /dev/null +++ b/docker/engine/macos-x86_64.Dockerfile @@ -0,0 +1,73 @@ +# syntax=docker/dockerfile:1.4 +FROM rust:1.88.0 AS base + +# Install dependencies +RUN apt-get update && apt-get install -y \ + git-lfs \ + protobuf-compiler \ + clang \ + cmake \ + patch \ + libxml2-dev \ + wget \ + xz-utils \ + curl \ + && rm -rf /var/lib/apt/lists/* + +# Install osxcross +RUN git config --global --add safe.directory '*' && \ + git clone https://github.com/tpoechtrager/osxcross /root/osxcross && \ + cd /root/osxcross && \ + wget -nc https://github.com/phracker/MacOSX-SDKs/releases/download/11.3/MacOSX11.3.sdk.tar.xz && \ + mv MacOSX11.3.sdk.tar.xz tarballs/ && \ + UNATTENDED=yes OSX_VERSION_MIN=10.7 ./build.sh + +# Add osxcross to PATH +ENV PATH="/root/osxcross/target/bin:$PATH" + +# Tell Clang/bindgen to use the macOS SDK, and nudge Clang to prefer osxcross binutils. +ENV OSXCROSS_SDK=MacOSX11.3.sdk \ + SDKROOT=/root/osxcross/target/SDK/MacOSX11.3.sdk \ + BINDGEN_EXTRA_CLANG_ARGS_X86_64_apple_darwin="--sysroot=/root/osxcross/target/SDK/MacOSX11.3.sdk -isystem /root/osxcross/target/SDK/MacOSX11.3.sdk/usr/include" \ + CFLAGS_X86_64_apple_darwin="-B/root/osxcross/target/bin" \ + CXXFLAGS_X86_64_apple_darwin="-B/root/osxcross/target/bin" \ + CARGO_TARGET_X86_64_APPLE_DARWIN_LINKER=x86_64-apple-darwin20.4-clang \ + CC_x86_64_apple_darwin=x86_64-apple-darwin20.4-clang \ + CXX_x86_64_apple_darwin=x86_64-apple-darwin20.4-clang++ \ + AR_X86_64_apple_darwin=x86_64-apple-darwin20.4-ar \ + RANLIB_X86_64_apple_darwin=x86_64-apple-darwin20.4-ranlib \ + MACOSX_DEPLOYMENT_TARGET=10.14 \ + RUSTFLAGS="--cfg tokio_unstable" \ + CARGO_INCREMENTAL=0 \ + CARGO_NET_GIT_FETCH_WITH_CLI=true + +# Set working directory +WORKDIR /build + +# Build for x86_64 macOS +FROM base AS x86_64-builder + +# Install macOS x86_64 target +RUN rustup target add x86_64-apple-darwin + +# Configure Cargo for cross-compilation (x86_64) +RUN mkdir -p /root/.cargo && \ + echo '\ +[target.x86_64-apple-darwin]\n\ +linker = "x86_64-apple-darwin20.4-clang"\n\ +ar = "x86_64-apple-darwin20.4-ar"\n\ +' > /root/.cargo/config.toml + +# Copy the source code +COPY . . + +# Build for x86_64 macOS +RUN --mount=type=cache,target=/usr/local/cargo/registry \ + --mount=type=cache,target=/usr/local/cargo/git \ + --mount=type=cache,target=/build/target \ + cargo build --bin rivet-engine --release --target x86_64-apple-darwin && \ + mkdir -p /artifacts && \ + cp target/x86_64-apple-darwin/release/rivet-engine /artifacts/rivet-engine-x86_64-apple-darwin + +# Default command to show help +CMD ["ls", "-la", "/artifacts"] \ No newline at end of file diff --git a/docker/engine/windows.Dockerfile b/docker/engine/windows.Dockerfile new file mode 100644 index 0000000000..5e798fd476 --- /dev/null +++ b/docker/engine/windows.Dockerfile @@ -0,0 +1,60 @@ +# syntax=docker/dockerfile:1.4 +FROM rust:1.88.0 + +# Install dependencies +RUN apt-get update && apt-get install -y \ + llvm-14-dev \ + libclang-14-dev \ + clang-14 \ + git-lfs \ + protobuf-compiler \ + gcc-mingw-w64-x86-64 \ + g++-mingw-w64-x86-64 \ + binutils-mingw-w64-x86-64 \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +# Switch MinGW-w64 to the POSIX threading model toolchain +RUN update-alternatives --set x86_64-w64-mingw32-gcc /usr/bin/x86_64-w64-mingw32-gcc-posix && \ + update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix + +# Install target +RUN rustup target add x86_64-pc-windows-gnu + +# Configure Cargo for Windows cross-compilation +RUN mkdir -p /root/.cargo && \ + echo '\ +[target.x86_64-pc-windows-gnu]\n\ +linker = "x86_64-w64-mingw32-gcc"\n\ +' > /root/.cargo/config.toml + +# ar = "x86_64-w64-mingw32-ar"\n + +# Set environment variables for cross-compilation +ENV CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=x86_64-w64-mingw32-gcc \ + CC_x86_64_pc_windows_gnu=x86_64-w64-mingw32-gcc \ + CXX_x86_64_pc_windows_gnu=x86_64-w64-mingw32-g++ \ + CC_x86_64-pc-windows-gnu=x86_64-w64-mingw32-gcc \ + CXX_x86_64-pc-windows-gnu=x86_64-w64-mingw32-g++ \ + LIBCLANG_PATH=/usr/lib/llvm-14/lib \ + CLANG_PATH=/usr/bin/clang-14 \ + RUSTFLAGS="--cfg tokio_unstable" \ + CARGO_INCREMENTAL=0 \ + CARGO_NET_GIT_FETCH_WITH_CLI=true + +# Set working directory +WORKDIR /build + +# Copy the source code +COPY . . + +# Build for Windows +RUN --mount=type=cache,target=/usr/local/cargo/registry \ + --mount=type=cache,target=/usr/local/cargo/git \ + --mount=type=cache,target=/build/target \ + cargo build --bin rivet-engine --release --target x86_64-pc-windows-gnu && \ + mkdir -p /artifacts && \ + cp target/x86_64-pc-windows-gnu/release/rivet-engine.exe /artifacts/rivet-engine-x86_64-pc-windows-gnu.exe + +# Default command to show help +CMD ["ls", "-la", "/artifacts"] diff --git a/docker/monolith/README.md b/docker/monolith/README.md deleted file mode 100644 index 5ada744a57..0000000000 --- a/docker/monolith/README.md +++ /dev/null @@ -1,70 +0,0 @@ -# Monolith Development Container - -## Operating - -Find our docs [here](https://rivet.gg/docs/self-hosting/single-container). - -## Development - -### Build & run - -Build & run the monolith container with extra logs enabled with: - -```bash -./scripts/docker/monolith_dev.ts -``` - -Flags: - -- `--no-build` Skip build step -- `--no-clean` Skips removing data dir - -Data will be stored in `/tmp/rivet-data`. - -### Build & run manually - -To build & run without using external scripts, run: - -```bash -docker build -f docker/universal/Dockerfile --target monolith -t rivet . -docker run --name rivet -v "$(pwd)/rivet-data:/data" -p 8080:8080 -p 9000:9000 -p 7080:7080 -p 7443:7443 -p 7500-7599:7500-7599 -p 7600-7699:7600-7699 --platform linux/amd64 rivet -``` - -### Logs - -Logs live in the `/var/log/{service name}` directory. - -You can read the logs by running: - -```bash -docker exec rivet cat /var/log/rivet-server/current -``` - -### Monitoring Vector - -Monitor `vector-server`: - -```bash -vector top --url http://0.0.0.0:9500/graphql -``` - -Monitor `vector-client`: - -```bash -vector top --url http://0.0.0.0:9510/graphql -``` - -### `s6-overlay` & generating services - -All required services run inside the container by default using `s6-overlay`. - -These services are auto-generated by the `./scripts/docker/generate.ts` script. - -### Port collisions - -Because all services live in the same address space, a lot of ports for dependent services are remapped internally. - -If a port uses numbers non-standard ports (e.g. ClickHouse has -[many ports](https://clickhouse.com/docs/en/guides/sre/network-ports) while Redis uses a single well-known -port 6379). - diff --git a/docker/monolith/build-scripts/deno.jsonc b/docker/monolith/build-scripts/deno.jsonc deleted file mode 100644 index b311abf54f..0000000000 --- a/docker/monolith/build-scripts/deno.jsonc +++ /dev/null @@ -1,10 +0,0 @@ -{ - "imports": { - "@std/fs": "jsr:@std/fs@^1.0.5", - "@std/path": "jsr:@std/path@^1.0.8", - "dedent": "npm:dedent@^1.5.3" - }, - "fmt": { - "useTabs": true - } -} diff --git a/docker/monolith/build-scripts/install.sh b/docker/monolith/build-scripts/install.sh deleted file mode 100755 index a93048cefb..0000000000 --- a/docker/monolith/build-scripts/install.sh +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env bash -set -euf -o pipefail - -TARGET_ARCH=$(uname -m | sed 's/aarch64/arm64/' | sed 's/x86_64/amd64/') - -apt-get update - -# Install required packages -# -# The FDB version should match `cluster::workflows::server::install::install_scripts::components::fdb::FDB_VERSION` - apt-get install -y \ - libclang-dev \ - ca-certificates \ - openssl \ - curl \ - postgresql-client \ - gpg \ - xz-utils \ - unzip \ - apt-transport-https \ - dirmngr \ - netcat-openbsd \ - procps - -(curl -L https://github.com/golang-migrate/migrate/releases/download/v4.18.1/migrate.linux-${TARGET_ARCH}.tar.gz | tar xvz) -mv migrate /usr/local/bin/migrate - -curl -fsSL https://deno.land/x/install/install.sh | sh -ln -s /root/.deno/bin/deno /usr/local/bin/deno - -curl -Lf -o /lib/libfdb_c.so "https://github.com/apple/foundationdb/releases/download/7.1.60/libfdb_c.x86_64.so" - -# === Traefik === -curl -sSLf https://github.com/traefik/traefik/releases/download/v${TRAEFIK_VERSION}/traefik_v${TRAEFIK_VERSION}_linux_${TARGET_ARCH}.tar.gz | \ - tar xz -C /usr/local/bin/ traefik - -# === CockroachDB === -useradd -m -s /bin/bash cockroachdb && \ - curl -sSLf https://binaries.cockroachdb.com/cockroach-v${COCKROACHDB_VERSION}.linux-${TARGET_ARCH}.tgz | tar xz && \ - cp -i cockroach-v${COCKROACHDB_VERSION}.linux-${TARGET_ARCH}/cockroach /usr/local/bin/ && \ - rm -rf cockroach-v${COCKROACHDB_VERSION}.linux-${TARGET_ARCH} - -# === Redis === -# TODO(RVT-4084): Switch to Valkey when Debian 13 released or ocmpile from source -useradd -m -s /bin/bash redis && \ - apt install -y redis-server redis-tools - -# === ClickHouse === -useradd -m -s /bin/bash clickhouse && \ - curl -fsSL 'https://packages.clickhouse.com/rpm/lts/repodata/repomd.xml.key' | gpg --dearmor -o /usr/share/keyrings/clickhouse-keyring.gpg && \ - echo "deb [signed-by=/usr/share/keyrings/clickhouse-keyring.gpg] https://packages.clickhouse.com/deb stable main" | tee /etc/apt/sources.list.d/clickhouse.list && \ - apt-get update && \ - apt-get install -y clickhouse-client clickhouse-server - -# === NATS === -useradd -m -s /bin/bash nats && \ - curl -sSLf https://github.com/nats-io/nats-server/releases/download/v${NATS_VERSION}/nats-server-v${NATS_VERSION}-linux-${TARGET_ARCH}.tar.gz | \ - tar xz -C /usr/local/bin/ --strip-components=1 nats-server-v${NATS_VERSION}-linux-${TARGET_ARCH}/nats-server - -# === SeaweedFS === -useradd -m -s /bin/bash seaweedfs && \ - curl -sSLf https://github.com/seaweedfs/seaweedfs/releases/download/${SEAWEEDFS_VERSION}/linux_${TARGET_ARCH}.tar.gz | tar xz -C /usr/local/bin/ - -# === FoundationDB === -# Client (for health checks) -curl -sSLf -o "/tmp/foundationdb-clients.deb" "https://github.com/apple/foundationdb/releases/download/${FDB_VERSION}/foundationdb-clients_${FDB_VERSION}-1_amd64.deb" -dpkg -i "/tmp/foundationdb-clients.deb" - -fdbcli --version - -# Server -curl -Lf -o "/tmp/foundationdb-server.deb" "https://github.com/apple/foundationdb/releases/download/${FDB_VERSION}/foundationdb-server_${FDB_VERSION}-1_amd64.deb" -dpkg -i "/tmp/foundationdb-server.deb" -rm -rf /etc/foundationdb - -fdbserver --version - -# Create log dir for internal FDB logs, since /var/log/foundationdb is used by S6 -mkdir /var/log/foundationdb-monitor -chown foundationdb:foundationdb /var/log/foundationdb-monitor - -# === Vector === -useradd -m -s /bin/bash vector-client && \ - useradd -m -s /bin/bash vector-server && \ - curl -sSLf https://packages.timber.io/vector/${VECTOR_VERSION}/vector_${VECTOR_VERSION}-1_${TARGET_ARCH}.deb -o /tmp/vector.deb && \ - dpkg -i /tmp/vector.deb && \ - rm /tmp/vector.deb - -# === S6 Overlay === -curl -sSLf https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-noarch.tar.xz -o /tmp/s6-overlay-noarch.tar.xz && \ - tar -C / -Jxpf /tmp/s6-overlay-noarch.tar.xz && \ - curl -sSLf https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-$(uname -m).tar.xz -o /tmp/s6-overlay-$(uname -m).tar.xz && \ - tar -C / -Jxpf /tmp/s6-overlay-$(uname -m).tar.xz - -# Setup S6 -deno run --allow-read --allow-write /tmp/build-scripts/setup_s6.ts - -# === Rivet === -useradd -m -s /bin/bash rivet-server -useradd -m -s /bin/bash rivet-guard diff --git a/docker/monolith/build-scripts/setup_s6.ts b/docker/monolith/build-scripts/setup_s6.ts deleted file mode 100755 index 8759b0df17..0000000000 --- a/docker/monolith/build-scripts/setup_s6.ts +++ /dev/null @@ -1,480 +0,0 @@ -#!/usr/bin/env -S deno run --vendor --allow-net --allow-env --allow-read --allow-write - -import { resolve } from "@std/path"; -import dedent from "dedent"; - -const basePath = "/etc/s6-overlay"; -const rcPath = resolve(basePath, "s6-rc.d"); -const scriptsPath = resolve(basePath, "scripts"); - -interface Service { - name: string; - command: string; - - /** Don't redirect logs. This will cause logs to log directly to stdout. */ - noRedirectLogs?: boolean; - - /** If a dir should be created in `/data/{service}`. */ - dataDir?: boolean; - - /** - * If this needs to run as root user. This will prevent creating a - * dedicated user for the service. - */ - rootUser?: boolean; - - /** - * Command to run to check this service's health. Will prevent services - * that depend on this service from starting until this command has - * succeeded. - */ - healthCheckCommand?: string; - - /** - * Wait for these dependencies to start before starting this service. - * - * See `healthCheckCommand`. - */ - dependencies?: string[]; - - /** - * Ports exposed by this service. - * - * Purely for documentation purposes. - */ - ports: Record; -} - -const services: Service[] = [ - { - name: "rivet-prestart", - command: "/root/run-scripts/prestart.sh", - noRedirectLogs: true, - rootUser: true, - ports: {}, - }, - { - name: "rivet-poststart", - command: "/root/run-scripts/poststart.sh", - noRedirectLogs: true, - dependencies: ["rivet-server"], - rootUser: true, - ports: {}, - }, - - { - name: "rivet-server", - command: "rivet-server start", - healthCheckCommand: "curl -f http://127.0.0.1:8090/health/liveness", - dependencies: [ - "cockroachdb", - "redis", - "clickhouse", - "nats", - "seaweedfs", - ], - ports: { - api: 8080, - apiInternal: 8081, - pegboard: 8082, - health: 8090, - metrics: 8091, - }, - }, - - { - name: "rivet-guard", - command: "traefik --configFile=/etc/rivet-guard/traefik.yaml", - ports: { - http: 7080, - metrics: 7443, - dashboard: 9980, - }, - }, - - { - name: "rivet-client", - command: "rivet-client -c /etc/rivet-client/config.jsonc", - dependencies: [ - "rivet-server", - "foundationdb", - ], - dataDir: true, - rootUser: true, - ports: { - runner: 6080, - metrics: 6090, - }, - }, - - { - name: "cockroachdb", - command: - "cockroach start-single-node --insecure --store=/data/cockroachdb --http-port 9200", - dataDir: true, - healthCheckCommand: "curl -f http://127.0.0.1:9200/health?ready=1", - ports: { http: 9200, sql: 26257 }, - }, - - { - name: "redis", - command: - "redis-server --dir /data/redis --requirepass password --save 60 1 --appendonly yes", - dataDir: true, - healthCheckCommand: "redis-cli ping", - ports: { default: 6379 }, - }, - - { - name: "clickhouse", - command: - "clickhouse-server --config-file=/etc/clickhouse-server/config.xml", - dataDir: true, - healthCheckCommand: - "clickhouse-client --port 9302 --password default --query 'SELECT 1'", - ports: { - http: 9300, - https: 9301, - tcp: 9302, - interserver_http: 9303, - metrics: 9304, - odbc: 9305, - mysql: 9306, - keeper: 9307, - raft: 9308, - }, - }, - - { - name: "nats", - command: "nats-server", - healthCheckCommand: "nc -z -w 1 127.0.0.1 4222", - ports: { default: 4222 }, - }, - - { - name: "seaweedfs", - // raftHashicorp speeds up initial leader election - command: ` - weed server \ - -dir /data/seaweedfs \ - -master.port=9402 \ - -master.raftBootstrap \ - -master.raftHashicorp \ - -volume.port 9400 \ - -filer.port=9403 \ - -s3 \ - -s3.config /etc/seaweedfs/s3.json \ - -s3.port=9000 \ - -s3.allowEmptyFolder=false \ - -s3.allowDeleteBucketNotEmpty=false - `, - dataDir: true, - healthCheckCommand: "curl -f http://127.0.0.1:9000/healthz", - ports: { - volume: 9400, - master: 9401, - filer: 9403, - - // 9000 is the standard port for S3 in development (based on Minio) - s3: 9000, - }, - }, - - { - name: "foundationdb", - command: "/usr/local/bin/foundationdb-entrypoint.sh", - dataDir: true, - // TODO: - rootUser: true, - healthCheckCommand: "fdbcli -C /data/foundationdb/fdb.cluster --exec status", - ports: { - fdb: 4500, - }, - }, - - { - name: "vector-server", - command: "vector -C /etc/vector-server", - dataDir: true, - ports: { - api: 9500, - source_vector: 6000, - source_tcp_json: 6100, - sink_prometheus_metrics: 9598, - }, - }, - - { - name: "vector-client", - command: "vector -C /etc/vector-client", - dataDir: true, - ports: { - api: 9510, - }, - }, -]; - -/** - * Create the `fs-setup` service. - * - * This sets up the filesystem to run the services: - * - * - Create `/data/{service}` dir - * - Create `/var/log/{service}` dir - */ -async function createFsSetupService() { - // MARK: Service - const servicePath = `${rcPath}/fs-setup`; - await Deno.mkdir(servicePath, { recursive: true }); - - await Deno.writeTextFile(`${servicePath}/type`, "oneshot"); - - await Deno.writeTextFile( - `${servicePath}/up`, - `${scriptsPath}/fs-setup.sh`, - ); - - // MARK: Script - // Generate required files for each service - let scriptContent = `#!/bin/sh\n`; - for (const service of services) { - // Data - if (service.dataDir) { - scriptContent += `mkdir -p /data/${service.name}\n`; - if (!service.rootUser) { - scriptContent += - `chown ${service.name}:${service.name} /data/${service.name}\n`; - } - } - - // Logs - if (!service.noRedirectLogs) { - scriptContent += `mkdir -p /var/log/${service.name}\n`; - scriptContent += `chown nobody:nogroup /var/log/${service.name}\n`; - scriptContent += `chmod 02755 /var/log/${service.name}\n`; - } - } - await Deno.writeTextFile( - `${scriptsPath}/fs-setup.sh`, - scriptContent, - ); - await Deno.chmod(`${scriptsPath}/fs-setup.sh`, 0o755); -} - -/** - * Create the `hosts-setup` service. - * - * This sets up the hosts file with DNS entries for each service. - * - * We do this in order to make configs easier to read to understand which - * service is being connected to. - * - * This also makes the configuration files consistent with networking inside a - * Docker Compose in order to keep configurations consistent. - */ -async function createHostsSetupService() { - // MARK: Service - const servicePath = `${rcPath}/hosts-setup`; - await Deno.mkdir(servicePath, { recursive: true }); - - await Deno.writeTextFile(`${servicePath}/type`, "oneshot"); - - await Deno.writeTextFile( - `${servicePath}/up`, - `${scriptsPath}/hosts-setup.sh`, - ); - - // MARK: Script - // Generate hosts file entries for each service - let scriptContent = `#!/bin/sh\n`; - for (const service of services) { - scriptContent += `echo "127.0.0.1 ${service.name}" >> /etc/hosts\n`; - } - await Deno.writeTextFile( - `${scriptsPath}/hosts-setup.sh`, - scriptContent, - ); - await Deno.chmod(`${scriptsPath}/hosts-setup.sh`, 0o755); -} - -/** - * Create a service & log service for each service. - * - * The log service writes the output to the file system for each system - * diagnosis. - */ -async function createServiceFiles(service: Service) { - // MARK: Service - const servicePath = `${rcPath}/${service.name}`; - await Deno.mkdir(servicePath, { recursive: true }); - - await Deno.writeTextFile(`${servicePath}/type`, "longrun"); - - if (!service.noRedirectLogs) { - await Deno.writeTextFile( - `${servicePath}/producer-for`, - `${service.name}-log`, - ); - } - - await Deno.mkdir(`${servicePath}/dependencies.d`, { recursive: true }); - await Deno.writeTextFile(`${servicePath}/dependencies.d/base`, ""); - await Deno.writeTextFile( - `${servicePath}/dependencies.d/fs-setup`, - "", - ); - await Deno.writeTextFile( - `${servicePath}/dependencies.d/hosts-setup`, - "", - ); - if (service.dependencies) { - for (const dependency of service.dependencies) { - await Deno.writeTextFile( - `${servicePath}/dependencies.d/${dependency}`, - "", - ); - await Deno.writeTextFile( - `${servicePath}/dependencies.d/${dependency}-health`, - "", - ); - } - } - - if (service.rootUser) { - await Deno.writeTextFile( - `${servicePath}/run`, - dedent`#!/bin/sh - exec 2>&1 - exec "${scriptsPath}/${service.name}-run.sh" - `, - ); - } else { - await Deno.writeTextFile( - `${servicePath}/run`, - dedent`#!/bin/sh - exec 2>&1 - exec su ${service.name} -c "${scriptsPath}/${service.name}-run.sh" - `, - ); - } - await Deno.chmod(`${servicePath}/run`, 0o755); - - // Write script - const runScriptPath = `${scriptsPath}/${service.name}-run.sh`; - await Deno.writeTextFile( - runScriptPath, - `#!/bin/sh\n${service.command}`, - ); - await Deno.chmod(runScriptPath, 0o755); - - // MARK: Logger - if (!service.noRedirectLogs) { - const logPath = `${rcPath}/${service.name}-log`; - await Deno.mkdir(logPath, { recursive: true }); - - await Deno.writeTextFile(`${logPath}/type`, "longrun"); - - await Deno.writeTextFile(`${logPath}/consumer-for`, `${service.name}`); - - await Deno.writeTextFile( - `${logPath}/pipeline-name`, - `${service.name}-pipeline`, - ); - - await Deno.mkdir(`${logPath}/dependencies.d`, { recursive: true }); - await Deno.writeTextFile( - `${logPath}/dependencies.d/fs-setup`, - "", - ); - - await Deno.writeTextFile( - `${logPath}/run`, - dedent` - #!/bin/sh - exec logutil-service /var/log/${service.name} - `, - ); - await Deno.chmod(`${logPath}/run`, 0o755); - } - - // MARK: Health Check - if (service.healthCheckCommand) { - // Write service - const healthcheckPath = `${rcPath}/${service.name}-health`; - await Deno.mkdir(healthcheckPath, { recursive: true }); - - await Deno.writeTextFile(`${healthcheckPath}/type`, "oneshot"); - - await Deno.writeTextFile( - `${healthcheckPath}/up`, - dedent` - ${scriptsPath}/${service.name}-healthcheck-loop.sh - `, - ); - await Deno.chmod(`${healthcheckPath}/up`, 0o755); - - // Write script - const healthcheckScriptPath = - `${scriptsPath}/${service.name}-healthcheck.sh`; - await Deno.writeTextFile( - healthcheckScriptPath, - dedent` - #!/bin/sh - ${service.healthCheckCommand} - `, - ); - await Deno.chmod(healthcheckScriptPath, 0o755); - - // Write checker loop - const healthcheckLoopScriptPath = - `${scriptsPath}/${service.name}-healthcheck-loop.sh`; - await Deno.writeTextFile( - healthcheckLoopScriptPath, - dedent` - #!/bin/sh - exec > /var/log/${service.name}-health.log 2>&1 - - start_time=\$(date +%s%3N) - while ! (echo 'Running health check'; ${scriptsPath}/${service.name}-healthcheck.sh); do - echo 'Health check failed' - sleep 0.5 - done - - end_time=\$(date +%s%3N) - elapsed_time=\$((end_time - start_time)) - echo "Health check passed in \${elapsed_time}ms." - - exit 0 - `, - ); - await Deno.chmod(healthcheckLoopScriptPath, 0o755); - } - - // MARK: Register service to be started - if (service.noRedirectLogs) { - await Deno.writeTextFile( - `${rcPath}/user/contents.d/${service.name}`, - "", - ); - } else { - await Deno.writeTextFile( - `${rcPath}/user/contents.d/${service.name}-pipeline`, - "", - ); - } -} - -async function generateConfigurations() { - await Deno.mkdir(`${rcPath}/user/contents.d`, { recursive: true }); - await Deno.mkdir(`${basePath}/scripts`, { recursive: true }); - - await createFsSetupService(); - await createHostsSetupService(); - - for (const service of services) { - await createServiceFiles(service); - } -} - -generateConfigurations(); diff --git a/docker/monolith/clickhouse/config.xml b/docker/monolith/clickhouse/config.xml deleted file mode 100644 index 9cf4b319e8..0000000000 --- a/docker/monolith/clickhouse/config.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - /data/clickhouse/ - - - trace - 1 - - - - - - localhost - 9307 - - - - - - 9307 - 1 - - - - - 10000 - 30000 - warning - - - - - 1 - localhost - 9308 - - - - - - /clickhouse/tables/{shard}/{database}/{table} - {replica} - - - - cluster1 - replica1 - 01 - - - - 9300 - 9301 - 9302 - 9303 - 9304 - 9305 - 9306 - - diff --git a/docker/monolith/clickhouse/users.xml b/docker/monolith/clickhouse/users.xml deleted file mode 100644 index 5cc16cef4d..0000000000 --- a/docker/monolith/clickhouse/users.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - 1 - - - default - - - default - - ::/0 - - - - default - - - 1 - 1 - 1 - - - - .* - - - - - - - - 10000000000 - 300 - 1000000000 - - - - - - - - 3600 - 0 - 0 - 0 - 0 - 0 - - - - diff --git a/docker/monolith/foundationdb/entrypoint.sh b/docker/monolith/foundationdb/entrypoint.sh deleted file mode 100644 index c5db0276cb..0000000000 --- a/docker/monolith/foundationdb/entrypoint.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -function configure_database() { - echo "Configuring database..." - until fdbcli -C /data/foundationdb/fdb.cluster --exec 'configure new single ssd' --timeout 10; do - sleep 2 - done - echo "Database configured." -} - -# Background process will wait until FoundationDB is up and configure it. -if [ ! -e /var/fdb/fdb.cluster ]; then - configure_database & -else - echo "Database already configured." -fi - -# Start FDB -echo 'fdb:fdb@127.0.0.1:4500' > /data/foundationdb/fdb.cluster -/usr/lib/foundationdb/fdbmonitor --conffile /etc/foundationdb/foundationdb.conf --lockfile /var/run/fdbmonitor.pid - diff --git a/docker/monolith/foundationdb/etc/foundationdb.conf b/docker/monolith/foundationdb/etc/foundationdb.conf deleted file mode 100644 index e026098eaf..0000000000 --- a/docker/monolith/foundationdb/etc/foundationdb.conf +++ /dev/null @@ -1,24 +0,0 @@ -[fdbmonitor] -user = foundationdb -group = foundationdb - -[general] -restart-delay = 60 -# Must be read-write, so we put it in the data dir -cluster-file = /data/foundationdb/fdb.cluster - -[fdbserver] -command = /usr/sbin/fdbserver -public-address = auto:$ID -listen-address = public -# Move data to data dir -datadir = /data/foundationdb/data/$ID -logdir = /var/log/foundationdb-monitor - -[fdbserver.4500] - -[backup_agent] -command = /usr/lib/foundationdb/backup_agent/backup_agent - -[backup_agent.1] - diff --git a/docker/monolith/rivet-client/config.yaml b/docker/monolith/rivet-client/config.yaml deleted file mode 100644 index a3f028889a..0000000000 --- a/docker/monolith/rivet-client/config.yaml +++ /dev/null @@ -1,38 +0,0 @@ -client: - data_dir: /data/rivet-client - runner: - flavor: isolate - # Enables running in non-privileged Docker containers - use_mounts: false - cluster: - # This is safe to hardcode - client_id: fc67e54e-5d6a-4726-ab23-77b0e54f068f - # This is hardcoded to match the value in rivet-server/config.jsonc - datacenter_id: f288913c-735d-4188-bf9b-2fcf6eac7b9c - api_endpoint: http://rivet-server:8080 - pegboard_endpoint: ws://rivet-server:8082 - network: - bind_ip: 127.0.0.1 - # Point to DNS name inside Docker container - lan_hostname: 127.0.0.1 - # Point to localhost since this is a dev instance - wan_hostname: 127.0.0.1 - # Corresponds to the port range configured in the `docker-compose.yml` - wan_port_range_min: 7600 - wan_port_range_max: 7699 - cni: - network_interface: eth0 - # Don't reserve any resources on dev instances - reserved_resources: - cpu: 0 - memory: 0 - logs: - redirect_logs: false - foundationdb: - cluster_description: fdb - cluster_id: fdb - addresses: - !static - - "127.0.0.1:4500" - vector: - address: vector-server:6100 diff --git a/docker/monolith/rivet-guard/traefik.yaml b/docker/monolith/rivet-guard/traefik.yaml deleted file mode 100644 index 610b9b918e..0000000000 --- a/docker/monolith/rivet-guard/traefik.yaml +++ /dev/null @@ -1,1122 +0,0 @@ -# DO NOT MODIFY -# -# Generated with scripts/docker/generate_configs.ts - -entryPoints: - traefik: - address: ':9980' - lb-7080: - address: ':7080' - lb-7443: - address: ':7443' - lb-7500-tcp: - address: ':7500/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7500-udp: - address: ':7500/udp' - udp: - timeout: 15s - lb-7501-tcp: - address: ':7501/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7501-udp: - address: ':7501/udp' - udp: - timeout: 15s - lb-7502-tcp: - address: ':7502/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7502-udp: - address: ':7502/udp' - udp: - timeout: 15s - lb-7503-tcp: - address: ':7503/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7503-udp: - address: ':7503/udp' - udp: - timeout: 15s - lb-7504-tcp: - address: ':7504/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7504-udp: - address: ':7504/udp' - udp: - timeout: 15s - lb-7505-tcp: - address: ':7505/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7505-udp: - address: ':7505/udp' - udp: - timeout: 15s - lb-7506-tcp: - address: ':7506/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7506-udp: - address: ':7506/udp' - udp: - timeout: 15s - lb-7507-tcp: - address: ':7507/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7507-udp: - address: ':7507/udp' - udp: - timeout: 15s - lb-7508-tcp: - address: ':7508/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7508-udp: - address: ':7508/udp' - udp: - timeout: 15s - lb-7509-tcp: - address: ':7509/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7509-udp: - address: ':7509/udp' - udp: - timeout: 15s - lb-7510-tcp: - address: ':7510/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7510-udp: - address: ':7510/udp' - udp: - timeout: 15s - lb-7511-tcp: - address: ':7511/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7511-udp: - address: ':7511/udp' - udp: - timeout: 15s - lb-7512-tcp: - address: ':7512/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7512-udp: - address: ':7512/udp' - udp: - timeout: 15s - lb-7513-tcp: - address: ':7513/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7513-udp: - address: ':7513/udp' - udp: - timeout: 15s - lb-7514-tcp: - address: ':7514/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7514-udp: - address: ':7514/udp' - udp: - timeout: 15s - lb-7515-tcp: - address: ':7515/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7515-udp: - address: ':7515/udp' - udp: - timeout: 15s - lb-7516-tcp: - address: ':7516/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7516-udp: - address: ':7516/udp' - udp: - timeout: 15s - lb-7517-tcp: - address: ':7517/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7517-udp: - address: ':7517/udp' - udp: - timeout: 15s - lb-7518-tcp: - address: ':7518/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7518-udp: - address: ':7518/udp' - udp: - timeout: 15s - lb-7519-tcp: - address: ':7519/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7519-udp: - address: ':7519/udp' - udp: - timeout: 15s - lb-7520-tcp: - address: ':7520/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7520-udp: - address: ':7520/udp' - udp: - timeout: 15s - lb-7521-tcp: - address: ':7521/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7521-udp: - address: ':7521/udp' - udp: - timeout: 15s - lb-7522-tcp: - address: ':7522/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7522-udp: - address: ':7522/udp' - udp: - timeout: 15s - lb-7523-tcp: - address: ':7523/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7523-udp: - address: ':7523/udp' - udp: - timeout: 15s - lb-7524-tcp: - address: ':7524/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7524-udp: - address: ':7524/udp' - udp: - timeout: 15s - lb-7525-tcp: - address: ':7525/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7525-udp: - address: ':7525/udp' - udp: - timeout: 15s - lb-7526-tcp: - address: ':7526/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7526-udp: - address: ':7526/udp' - udp: - timeout: 15s - lb-7527-tcp: - address: ':7527/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7527-udp: - address: ':7527/udp' - udp: - timeout: 15s - lb-7528-tcp: - address: ':7528/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7528-udp: - address: ':7528/udp' - udp: - timeout: 15s - lb-7529-tcp: - address: ':7529/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7529-udp: - address: ':7529/udp' - udp: - timeout: 15s - lb-7530-tcp: - address: ':7530/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7530-udp: - address: ':7530/udp' - udp: - timeout: 15s - lb-7531-tcp: - address: ':7531/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7531-udp: - address: ':7531/udp' - udp: - timeout: 15s - lb-7532-tcp: - address: ':7532/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7532-udp: - address: ':7532/udp' - udp: - timeout: 15s - lb-7533-tcp: - address: ':7533/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7533-udp: - address: ':7533/udp' - udp: - timeout: 15s - lb-7534-tcp: - address: ':7534/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7534-udp: - address: ':7534/udp' - udp: - timeout: 15s - lb-7535-tcp: - address: ':7535/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7535-udp: - address: ':7535/udp' - udp: - timeout: 15s - lb-7536-tcp: - address: ':7536/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7536-udp: - address: ':7536/udp' - udp: - timeout: 15s - lb-7537-tcp: - address: ':7537/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7537-udp: - address: ':7537/udp' - udp: - timeout: 15s - lb-7538-tcp: - address: ':7538/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7538-udp: - address: ':7538/udp' - udp: - timeout: 15s - lb-7539-tcp: - address: ':7539/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7539-udp: - address: ':7539/udp' - udp: - timeout: 15s - lb-7540-tcp: - address: ':7540/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7540-udp: - address: ':7540/udp' - udp: - timeout: 15s - lb-7541-tcp: - address: ':7541/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7541-udp: - address: ':7541/udp' - udp: - timeout: 15s - lb-7542-tcp: - address: ':7542/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7542-udp: - address: ':7542/udp' - udp: - timeout: 15s - lb-7543-tcp: - address: ':7543/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7543-udp: - address: ':7543/udp' - udp: - timeout: 15s - lb-7544-tcp: - address: ':7544/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7544-udp: - address: ':7544/udp' - udp: - timeout: 15s - lb-7545-tcp: - address: ':7545/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7545-udp: - address: ':7545/udp' - udp: - timeout: 15s - lb-7546-tcp: - address: ':7546/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7546-udp: - address: ':7546/udp' - udp: - timeout: 15s - lb-7547-tcp: - address: ':7547/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7547-udp: - address: ':7547/udp' - udp: - timeout: 15s - lb-7548-tcp: - address: ':7548/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7548-udp: - address: ':7548/udp' - udp: - timeout: 15s - lb-7549-tcp: - address: ':7549/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7549-udp: - address: ':7549/udp' - udp: - timeout: 15s - lb-7550-tcp: - address: ':7550/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7550-udp: - address: ':7550/udp' - udp: - timeout: 15s - lb-7551-tcp: - address: ':7551/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7551-udp: - address: ':7551/udp' - udp: - timeout: 15s - lb-7552-tcp: - address: ':7552/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7552-udp: - address: ':7552/udp' - udp: - timeout: 15s - lb-7553-tcp: - address: ':7553/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7553-udp: - address: ':7553/udp' - udp: - timeout: 15s - lb-7554-tcp: - address: ':7554/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7554-udp: - address: ':7554/udp' - udp: - timeout: 15s - lb-7555-tcp: - address: ':7555/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7555-udp: - address: ':7555/udp' - udp: - timeout: 15s - lb-7556-tcp: - address: ':7556/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7556-udp: - address: ':7556/udp' - udp: - timeout: 15s - lb-7557-tcp: - address: ':7557/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7557-udp: - address: ':7557/udp' - udp: - timeout: 15s - lb-7558-tcp: - address: ':7558/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7558-udp: - address: ':7558/udp' - udp: - timeout: 15s - lb-7559-tcp: - address: ':7559/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7559-udp: - address: ':7559/udp' - udp: - timeout: 15s - lb-7560-tcp: - address: ':7560/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7560-udp: - address: ':7560/udp' - udp: - timeout: 15s - lb-7561-tcp: - address: ':7561/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7561-udp: - address: ':7561/udp' - udp: - timeout: 15s - lb-7562-tcp: - address: ':7562/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7562-udp: - address: ':7562/udp' - udp: - timeout: 15s - lb-7563-tcp: - address: ':7563/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7563-udp: - address: ':7563/udp' - udp: - timeout: 15s - lb-7564-tcp: - address: ':7564/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7564-udp: - address: ':7564/udp' - udp: - timeout: 15s - lb-7565-tcp: - address: ':7565/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7565-udp: - address: ':7565/udp' - udp: - timeout: 15s - lb-7566-tcp: - address: ':7566/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7566-udp: - address: ':7566/udp' - udp: - timeout: 15s - lb-7567-tcp: - address: ':7567/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7567-udp: - address: ':7567/udp' - udp: - timeout: 15s - lb-7568-tcp: - address: ':7568/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7568-udp: - address: ':7568/udp' - udp: - timeout: 15s - lb-7569-tcp: - address: ':7569/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7569-udp: - address: ':7569/udp' - udp: - timeout: 15s - lb-7570-tcp: - address: ':7570/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7570-udp: - address: ':7570/udp' - udp: - timeout: 15s - lb-7571-tcp: - address: ':7571/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7571-udp: - address: ':7571/udp' - udp: - timeout: 15s - lb-7572-tcp: - address: ':7572/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7572-udp: - address: ':7572/udp' - udp: - timeout: 15s - lb-7573-tcp: - address: ':7573/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7573-udp: - address: ':7573/udp' - udp: - timeout: 15s - lb-7574-tcp: - address: ':7574/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7574-udp: - address: ':7574/udp' - udp: - timeout: 15s - lb-7575-tcp: - address: ':7575/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7575-udp: - address: ':7575/udp' - udp: - timeout: 15s - lb-7576-tcp: - address: ':7576/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7576-udp: - address: ':7576/udp' - udp: - timeout: 15s - lb-7577-tcp: - address: ':7577/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7577-udp: - address: ':7577/udp' - udp: - timeout: 15s - lb-7578-tcp: - address: ':7578/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7578-udp: - address: ':7578/udp' - udp: - timeout: 15s - lb-7579-tcp: - address: ':7579/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7579-udp: - address: ':7579/udp' - udp: - timeout: 15s - lb-7580-tcp: - address: ':7580/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7580-udp: - address: ':7580/udp' - udp: - timeout: 15s - lb-7581-tcp: - address: ':7581/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7581-udp: - address: ':7581/udp' - udp: - timeout: 15s - lb-7582-tcp: - address: ':7582/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7582-udp: - address: ':7582/udp' - udp: - timeout: 15s - lb-7583-tcp: - address: ':7583/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7583-udp: - address: ':7583/udp' - udp: - timeout: 15s - lb-7584-tcp: - address: ':7584/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7584-udp: - address: ':7584/udp' - udp: - timeout: 15s - lb-7585-tcp: - address: ':7585/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7585-udp: - address: ':7585/udp' - udp: - timeout: 15s - lb-7586-tcp: - address: ':7586/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7586-udp: - address: ':7586/udp' - udp: - timeout: 15s - lb-7587-tcp: - address: ':7587/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7587-udp: - address: ':7587/udp' - udp: - timeout: 15s - lb-7588-tcp: - address: ':7588/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7588-udp: - address: ':7588/udp' - udp: - timeout: 15s - lb-7589-tcp: - address: ':7589/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7589-udp: - address: ':7589/udp' - udp: - timeout: 15s - lb-7590-tcp: - address: ':7590/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7590-udp: - address: ':7590/udp' - udp: - timeout: 15s - lb-7591-tcp: - address: ':7591/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7591-udp: - address: ':7591/udp' - udp: - timeout: 15s - lb-7592-tcp: - address: ':7592/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7592-udp: - address: ':7592/udp' - udp: - timeout: 15s - lb-7593-tcp: - address: ':7593/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7593-udp: - address: ':7593/udp' - udp: - timeout: 15s - lb-7594-tcp: - address: ':7594/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7594-udp: - address: ':7594/udp' - udp: - timeout: 15s - lb-7595-tcp: - address: ':7595/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7595-udp: - address: ':7595/udp' - udp: - timeout: 15s - lb-7596-tcp: - address: ':7596/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7596-udp: - address: ':7596/udp' - udp: - timeout: 15s - lb-7597-tcp: - address: ':7597/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7597-udp: - address: ':7597/udp' - udp: - timeout: 15s - lb-7598-tcp: - address: ':7598/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7598-udp: - address: ':7598/udp' - udp: - timeout: 15s - lb-7599-tcp: - address: ':7599/tcp' - transport: - respondingTimeouts: - readTimeout: 12h - writeTimeout: 12h - idleTimeout: 30s - lb-7599-udp: - address: ':7599/udp' - udp: - timeout: 15s -api: - insecure: true -log: - level: INFO -accessLog: {} -providers: - providersThrottleDuration: 0.025s - http: - endpoint: >- - http://rivet-server:8081/traefik-provider/config/game-guard?datacenter=f288913c-735d-4188-bf9b-2fcf6eac7b9c - pollInterval: 0.5s diff --git a/docker/monolith/rivet-server/config.yaml b/docker/monolith/rivet-server/config.yaml deleted file mode 100644 index aa8e8d290b..0000000000 --- a/docker/monolith/rivet-server/config.yaml +++ /dev/null @@ -1,64 +0,0 @@ -server: - rivet: - auth: - access_kind: development - - ui: - public_origin_regex: .* - - guard: - # TLS not configured for local development - tls_enabled: false - # Corresponds to the ports configured in the `docker-compose.yml` - http_port: 7080 - https_port: 7443 - min_ingress_port_tcp: 7500 - max_ingress_port_tcp: 7599 - min_ingress_port_udp: 7500 - max_ingress_port_udp: 7599 - cockroachdb: - url: postgresql://cockroachdb:26257/defaultdb?sslmode=disable - username: root - redis: - ephemeral: - url: redis://redis:6379 - password: password - persistent: - url: redis://redis:6379 - password: password - clickhouse: - http_url: http://clickhouse:9300 - native_url: clickhouse://clickhouse:9302 - username: default - password: default - provision_users: - vector: - username: vector - password: vector - role: write - s3: - region: us-east-1 - endpoint_internal: http://seaweedfs:9000 - endpoint_edge_internal: http://seaweedfs:9000 - endpoint_external: http://127.0.0.1:9000 - access_key_id: admin - secret_access_key: admin - nats: - urls: - - nats://nats:4222 - - # IMPORTANT: - # - Generate your own JWT tokens before shipping to production as seen in the - # self-hosting documentation. - # - Do not include the private key in this file. Instead, use the env var - # `RIVET__SERVER__JWT__PRIVATE`. - jwt: - public: | - -----BEGIN PUBLIC KEY----- - MCowBQYDK2VwAyEAx7S9ab9ErA50y0tVfFro919+BBxFSuwMKmcJ5QI853Y= - -----END PUBLIC KEY----- - private: | - -----BEGIN PRIVATE KEY----- - MC4CAQAwBQYDK2VwBCIEIDI+WHFytxvdtfGot36NMCI26s2Yp0+E5u9OiPf3NQX3 - -----END PRIVATE KEY----- - diff --git a/docker/monolith/run-scripts/poststart.sh b/docker/monolith/run-scripts/poststart.sh deleted file mode 100755 index 5048a1c966..0000000000 --- a/docker/monolith/run-scripts/poststart.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -cat << EOF -Rivet started. -EOF - -# Sleep for infinity since this service will be restarted if it exits -sleep infinity - diff --git a/docker/monolith/run-scripts/prestart.sh b/docker/monolith/run-scripts/prestart.sh deleted file mode 100755 index 7573e28b03..0000000000 --- a/docker/monolith/run-scripts/prestart.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh -cat << EOF -Welcome to Rivet - -Configuration: - - Rivet Server: - - Dashboard: http://127.0.0.1:8080/ui/ - API: 127.0.0.1:8080 - Edge API: 127.0.0.1:8081 - Orchestrator: 127.0.0.1:8082 - Object Storage: 127.0.0.1:9000 - - Rivet Guard: - - HTTP: 127.0.0.1:7080 - HTTPS: 127.0.0.1:7443 - TCP & UDP: 127.0.0.1:7500-7599 - - Rivet Client: - - Host Networking: 127.0.0.1:7600-7699 - -Resources: - - Quickstart: https://rivet.gg/docs/quickstart - Operation: https://rivet.gg/docs/self-hosting - Documentation: https://rivet.gg/docs - Discord: https://rivet.gg/discord - -Starting Rivet... -EOF - -# Sleep for infinity since this service will be restarted if it exits -sleep infinity - diff --git a/docker/monolith/seaweedfs/s3.json b/docker/monolith/seaweedfs/s3.json deleted file mode 100644 index 9b80248742..0000000000 --- a/docker/monolith/seaweedfs/s3.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "identities": [ - { - "name": "admin", - "credentials": [ - { - "accessKey": "admin", - "secretKey": "admin" - } - ], - "actions": [ - "Admin", - "Read", - "ReadAcp", - "List", - "Tagging", - "Write", - "WriteAcp" - ] - } - ] -} diff --git a/docker/monolith/vector-client/vector.yaml b/docker/monolith/vector-client/vector.yaml deleted file mode 100644 index 1f892ffb6c..0000000000 --- a/docker/monolith/vector-client/vector.yaml +++ /dev/null @@ -1,110 +0,0 @@ -# See production config at -# ee/packages/services/cluster/src/workflows/server/install/install_scripts/components/vector.rs - -data_dir: /data/vector-client - -api: - enabled: true - address: 0.0.0.0:9510 - playground: false - -sources: - prometheus_pegboard: - type: prometheus_scrape - endpoints: - - http://rivet-client:6090 - scrape_interval_secs: 15 - - pegboard_manager: - type: file - include: - - /data/rivet-client/log - - pegboard_v8_isolate_runner: - type: file - include: - - /data/rivet-client/runner/log - - pegboard_container_runners: - type: file - include: - - /data/rivet-client/actors/*/log - -transforms: - filter_metrics: - type: filter - inputs: - - prometheus_pegboard - condition: '!starts_with!(.name, "go_") && !starts_with!(.name, "promhttp_")' - - metrics_add_meta: - type: remap - inputs: - - filter_metrics - source: | - .tags.server_id = "fc67e54e-5d6a-4726-ab23-77b0e54f068f" - .tags.datacenter_id = "f288913c-735d-4188-bf9b-2fcf6eac7b9c" - .tags.cluster_id = "unknown" - .tags.pool_type = "pegboard_isolate" - .tags.public_ip = "127.0.0.1" - - pegboard_manager_add_meta: - type: remap - inputs: - - pegboard_manager - source: | - .source = "pegboard_manager" - - .client_id = "fc67e54e-5d6a-4726-ab23-77b0e54f068f" - .server_id = "fc67e54e-5d6a-4726-ab23-77b0e54f068f" - .datacenter_id = "f288913c-735d-4188-bf9b-2fcf6eac7b9c" - .tags.cluster_id = "unknown" - .pool_type = "pegboard_isolate" - .public_ip = "127.0.0.1" - - pegboard_v8_isolate_runner_add_meta: - type: remap - inputs: - - pegboard_v8_isolate_runner - source: | - .source = "pegboard_v8_isolate_runner" - - .client_id = "fc67e54e-5d6a-4726-ab23-77b0e54f068f" - .server_id = "fc67e54e-5d6a-4726-ab23-77b0e54f068f" - .datacenter_id = "f288913c-735d-4188-bf9b-2fcf6eac7b9c" - .tags.cluster_id = "unknown" - .pool_type = "pegboard_isolate" - .public_ip = "127.0.0.1" - - pegboard_container_runner_add_meta: - type: remap - inputs: - - pegboard_container_runners - source: | - .source = "pegboard_container_runner" - .actor_id = parse_regex!(.file, r'/etc/pegboard/actors/(?P[0-9a-fA-F-]+)/log').actor_id - - .client_id = "fc67e54e-5d6a-4726-ab23-77b0e54f068f" - .server_id = "fc67e54e-5d6a-4726-ab23-77b0e54f068f" - .datacenter_id = "f288913c-735d-4188-bf9b-2fcf6eac7b9c" - .cluster_id = "unknown" - .pool_type = "pegboard_isolate" - .public_ip = "127.0.0.1" - -sinks: - vector_sink: - type: vector - inputs: - - metrics_add_meta - - pegboard_manager_add_meta - - pegboard_v8_isolate_runner_add_meta - - pegboard_container_runner_add_meta - address: vector-server:6000 - healthcheck: - enabled: false - compression: true - buffer: - type: disk - max_size: 268435488 - when_full: block - diff --git a/docker/monolith/vector-server/vector.yaml b/docker/monolith/vector-server/vector.yaml deleted file mode 100644 index fe5bbba465..0000000000 --- a/docker/monolith/vector-server/vector.yaml +++ /dev/null @@ -1,129 +0,0 @@ -# See production config at ee/infra/tf/vector/vector.tf - -data_dir: /data/vector-server - -api: - enabled: true - address: 0.0.0.0:9500 - playground: false - -sources: - vector: - type: vector - address: 0.0.0.0:6000 - - tcp_json: - type: socket - mode: tcp - address: 0.0.0.0:6100 - decoding: - codec: json - - vector_metrics: - type: internal_metrics - - vector_logs: - type: internal_logs - -transforms: - actors: - type: filter - inputs: - - vector - - tcp_json - condition: - type: vrl - source: .source == "actors" - - job_run: - type: filter - inputs: - - vector - - tcp_json - condition: - type: vrl - source: .source == "job_run" - - pegboard: - type: filter - inputs: - - vector - condition: - type: vrl - source: .source == "pegboard_manager" || .source == "pegboard_v8_isolate_runner" - - pegboard_container_runner: - type: filter - inputs: - - vector - condition: - type: vrl - source: .source == "pegboard_container_runner" - - actors_transform: - type: remap - inputs: - - actors - source: | - # Add namespace label to actor logs - .namespace = "rivet" - -sinks: - prom_exporter: - type: prometheus_exporter - inputs: - - vector - - vector_metrics - address: 0.0.0.0:9598 - - console: - type: console - inputs: - - vector_logs - encoding: - codec: text - - clickhouse_actor_logs: - type: clickhouse - inputs: - - actors_transform - compression: gzip - endpoint: http://clickhouse:9300 - database: db_pegboard_actor_log - table: actor_logs3 - auth: - strategy: basic - user: vector - password: vector - batch: - timeout_secs: 1.0 - - clickhouse_job_run_logs: - type: clickhouse - inputs: - - job_run - compression: gzip - endpoint: http://clickhouse:9300 - database: db_job_log - table: run_logs - auth: - strategy: basic - user: vector - password: vector - batch: - timeout_secs: 1.0 - - pegboard_logs: - type: "file" - inputs: ["pegboard"] - path: "/var/log/vector/pegboard/%Y-%m-%d.log" - encoding: - codec: "text" - - pegboard_container_runner_logs: - type: "file" - inputs: ["pegboard_container_runner"] - path: "/var/log/vector/pegboard_container_runner/%Y-%m-%d.log" - encoding: - codec: "text" - diff --git a/docker/prod-file-system/.gitattributes b/docker/prod-file-system/.gitattributes new file mode 100644 index 0000000000..447edeb5c2 --- /dev/null +++ b/docker/prod-file-system/.gitattributes @@ -0,0 +1 @@ +. linguist-generated=true diff --git a/docker/prod-file-system/README.md b/docker/prod-file-system/README.md new file mode 100644 index 0000000000..4b02525eeb --- /dev/null +++ b/docker/prod-file-system/README.md @@ -0,0 +1,76 @@ +# dev - Auto-generated Docker Compose Template + +> ! **Auto-generated**: This directory and its contents are automatically generated by `docker/template/`. Do not edit these files directly as your changes will be overwritten. + +## Overview + +This Docker Compose configuration provides a complete development environment for Rivet with the following services: + +- **Rivet Engine**: Main orchestration service +- **Rivet Shell**: Interactive shell for debugging +- **Runner**: Executes user code +- **ClickHouse**: Analytics and time-series database +- **NATS**: Message broker +- **PostgreSQL**: Relational database +- **Vector Server**: Log aggregation and processing +- **OpenTelemetry Collector**: Observability data collection + +## Port Configuration + +| Service | Port(s) | Description | +|---------|---------|-------------| +| Rivet Engine | 6420 | Public endpoint | +| Runner | 5050 | Code execution service | +| NATS | 4222 | Message broker | +| PostgreSQL | 5432 | Database | +| ClickHouse HTTP | 9300 | Database HTTP interface | +| ClickHouse Native | 9301 | Database native protocol | +| OpenTelemetry gRPC | 4317 | OTLP gRPC endpoint | +| OpenTelemetry HTTP | 4318 | OTLP HTTP endpoint | + +## Template Configuration + +**Template Name**: `dev` +**Base Port**: `6420` +**Network Mode**: `bridge` + +### Datacenters +- **1**: 1 engine(s), 1 runner(s) + +## Usage + +1. Start all services: + ```bash + docker-compose up -d + ``` + +2. Check service health: + ```bash + docker-compose ps + ``` + +3. View logs: + ```bash + docker-compose logs -f [service-name] + ``` + +4. Stop all services: + ```bash + docker-compose down + ``` + +## Generated Files + +This template generates the following files and directories: +- `docker-compose.yml` - Main Docker Compose configuration +- `core/` - Core services shared across datacenters: + - `clickhouse/` - ClickHouse configuration and initialization + - `vector-server/` - Vector aggregator configuration + - `otel-collector-server/` - OpenTelemetry Collector server configuration +- `datacenters/` - Datacenter-specific configurations: + - `1/` - Configuration for datacenter 1: + - `postgres/` - PostgreSQL setup scripts + - `rivet-engine/` - Rivet Engine configuration + - `vector-client/` - Vector client configuration + - `otel-collector-client/` - OpenTelemetry Collector client configuration +- `README.md` - This file diff --git a/docker/prod-file-system/docker-compose.yml b/docker/prod-file-system/docker-compose.yml new file mode 100644 index 0000000000..8bf0241c51 --- /dev/null +++ b/docker/prod-file-system/docker-compose.yml @@ -0,0 +1,42 @@ +services: + rivet-engine: + build: + context: ../.. + dockerfile: docker/universal/Dockerfile + target: engine-full + restart: unless-stopped + command: /usr/bin/rivet-engine start + environment: + - RIVET__FILE_SYSTEM__PATH=/var/lib/rivet-engine + volumes: + - ./rivet-engine/config.jsonc:/etc/rivet/config.jsonc:ro + - rivet-engine-data:/var/lib/rivet-engine + ports: + - '6420:6420' + healthcheck: + test: + - CMD + - curl + - '-f' + - http://127.0.0.1:6421/health + interval: 2s + timeout: 10s + retries: 10 + start_period: 30s + runner: + build: + context: ../.. + dockerfile: docker/runner/Dockerfile + platform: linux/amd64 + restart: unless-stopped + environment: + - RIVET_ENDPOINT=http://rivet-engine:6420 + - RUNNER_HOST=runner + stop_grace_period: 4s + ports: + - '5050:5050' + depends_on: + rivet-engine: + condition: service_healthy +volumes: + rivet-engine-data: diff --git a/docker/prod-file-system/rivet-engine/config.jsonc b/docker/prod-file-system/rivet-engine/config.jsonc new file mode 100644 index 0000000000..2c63c08510 --- /dev/null +++ b/docker/prod-file-system/rivet-engine/config.jsonc @@ -0,0 +1,2 @@ +{ +} diff --git a/docker/template/README.md b/docker/template/README.md new file mode 100644 index 0000000000..6ee952e7a2 --- /dev/null +++ b/docker/template/README.md @@ -0,0 +1,20 @@ +# Docker Compose Template Generator + +This package generates Docker Compose configurations for Rivet environments with different scaling configurations. + +Run with: + +```sh +pnpm start +``` + +## Port Management + +The template uses a base port (default: 6420) and assigns sequential ports to services: + +- 6420: Rivet Engine +- 5050: Runner (mapped from original) +- 4222: NATS (mapped from original) +- 3100: Grafana (mapped from original 3000) +- 9300/9301: ClickHouse (mapped from original) +- 4317/4318/8888: OpenTelemetry Collector (mapped from original) diff --git a/docker/template/grafana-dashboards/api.json b/docker/template/grafana-dashboards/api.json new file mode 100644 index 0000000000..34004bf134 --- /dev/null +++ b/docker/template/grafana-dashboards/api.json @@ -0,0 +1,1172 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 7, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 24, + "panels": [], + "title": "API", + "type": "row" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 26, + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_api_request_duration'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Request Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 27, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_api_request_pending'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Requests Pending", + "transformations": [ + { + "id": "groupingToMatrix", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 10 + }, + "id": 32, + "interval": "15s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n sum(Sum) / sum(Count) as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nHAVING sum(Count) > 0\nORDER BY time", + "refId": "A" + } + ], + "title": "Duration (avg)", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 10 + }, + "id": 33, + "interval": "15s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label, bounds, idx\nORDER BY time", + "refId": "A" + } + ], + "title": "Duration (p95)", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "bounds" + } + }, + { + "id": "convertFieldType", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 16, + "y": 10 + }, + "id": 34, + "interval": "15s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n Attributes['method'] as method,\n Attributes['path'] as path,\n histogramQuantile(arrayZip(ExplicitBounds, BucketCounts), 0.99) as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND Attributes['watch'] = '0'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, method, path\nORDER BY time", + "refId": "A" + } + ], + "title": "Duration (p99)", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 19 + }, + "id": 25, + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path']\n ) as label,\n sum(Value) / $__interval_ms * 1000 as value\n -- (\n -- SELECT\n -- sum(Value) / $__interval_ms * 1000 as value\n -- FROM otel.otel_metrics_sum\n -- WHERE MetricName = 'rivet_api_request_total'\n -- AND $__conditionalAll(Attributes['path'], $path)\n -- AND $__conditionalAll(Attributes['method'], $method)\n -- AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n -- AND $__timeFilter(TimeUnix)\n -- ) as prev_value\n -- lagInFrame(value, 1, value) OVER (ORDER BY time) as previous_value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_api_request_total'\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Request Rate", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 19 + }, + "id": 28, + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Name", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}: {{status}} ({{error_code}})", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path'], ': ',\n Attributes['status'], ' (',\n Attributes['error_code'], ')'\n ) as label,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_api_request_errors'\n AND Attributes['status'] LIKE '4%'\n AND Attributes['error_code'] NOT IN ('API_CANCELLED', 'CAPTCHA_CAPTCHA_REQUIRED')\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Error Rate (4xx)", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\label" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 16, + "y": 19 + }, + "id": 31, + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{datacenter_id}} {{method}} {{path}}: {{status}} ({{error_code}})", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n concat(\n ResourceAttributes['datacenter_id'], ' ',\n Attributes['method'], ' ',\n Attributes['path'], ': ',\n Attributes['error_code'], ' (',\n Attributes['status'], ')'\n ) as label,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_api_request_errors'\n AND Attributes['status'] LIKE '5%'\n AND Attributes['error_code']-- NOT IN ('API_CANCELLED', 'CAPTCHA_CAPTCHA_REQUIRED')\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Error Rate (5xx)", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "log": 2, + "type": "log" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "percent" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 28 + }, + "id": 35, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{method}} {{path}}: {{status}} {{error_code}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['method'] as method,\n Attributes['path'] as path,\n Attributes['status'] as status,\n Attributes['error_code'] as error_code,\n sum(Count) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_api_request_duration'\n AND (Attributes['status'] = '200' OR Attributes['status'] LIKE '5%')\n AND Attributes['error_code']-- NOT IN ('API_CANCELLED', 'CAPTCHA_CAPTCHA_REQUIRED')\n AND $__conditionalAll(Attributes['path'], $path)\n AND $__conditionalAll(Attributes['method'], $method)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, method, path, status, error_code\nORDER BY time", + "refId": "A" + } + ], + "title": "200 vs 5xx (4xx excluded)", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "30s", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request_errors' ORDER BY datacenter_id", + "includeAll": true, + "label": "Datacenter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request_errors' ORDER BY datacenter_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['path'] as path FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) ORDER BY path", + "includeAll": true, + "label": "Path", + "multi": true, + "name": "path", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['path'] as path FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) ORDER BY path", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['method'] as method FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) AND $__conditionalAll(Attributes['path'], $path) ORDER BY method", + "includeAll": true, + "label": "Method", + "multi": true, + "name": "method", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['method'] as method FROM otel.otel_metrics_sum WHERE MetricName = 'rivet_api_request' AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id) AND $__conditionalAll(Attributes['path'], $path) ORDER BY method", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-24h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "API", + "uid": "feg8y72gpm2o0c", + "version": 1, + "weekStart": "" +} diff --git a/docker/template/grafana-dashboards/cache.json b/docker/template/grafana-dashboards/cache.json new file mode 100644 index 0000000000..5d762023ea --- /dev/null +++ b/docker/template/grafana-dashboards/cache.json @@ -0,0 +1,1176 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 4, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 10, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n CASE\n WHEN ResourceAttributes['datacenter_id'] != '' AND ResourceAttributes['server_id'] != '' THEN concat(ResourceAttributes['datacenter_id'], ' - ', ResourceAttributes['server_id'])\n ELSE 'Route Cache Size'\n END as label,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_route_cache_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, label\nORDER BY time", + "refId": "A" + } + ], + "title": "Route Cache Size", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "label", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\label" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 11, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_rate_limiter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Rate Limiters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 12, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_in_flight_counter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "In-Flight Counters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 8 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_tcp_connection_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active TCP Connections", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 8 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_tcp_connection'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "TCP Connection Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 8 + }, + "id": 1, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_tcp_connection_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "TCP Connection Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 16 + }, + "id": 7, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_proxy_request_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Proxy Requests", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 16 + }, + "id": 8, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_proxy_request'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Proxy Request Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 16 + }, + "id": 9, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_proxy_request_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Proxy Request Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 24 + }, + "id": 6, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_resolve_route_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Resolve Route Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "description": "", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "description": "", + "includeAll": true, + "label": "Dataceter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "description": "", + "includeAll": true, + "label": "Server ID", + "multi": true, + "name": "server_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Rivet Guard", + "uid": "cen785ige8fswd", + "version": 1, + "weekStart": "" +} diff --git a/docker/template/grafana-dashboards/futures.json b/docker/template/grafana-dashboards/futures.json new file mode 100644 index 0000000000..0c992c4bcb --- /dev/null +++ b/docker/template/grafana-dashboards/futures.json @@ -0,0 +1,208 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_instrumented_future_duration'\n AND $__conditionalAll(Attributes['name'], $name)\n AND $__conditionalAll(Attributes['location'], $location)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Instrumented Future Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "30s", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['name'] as name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY name", + "includeAll": true, + "label": "Name", + "multi": true, + "name": "name", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['name'] as name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY name", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['location'] as location FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY location", + "includeAll": true, + "label": "Location", + "multi": true, + "name": "location", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['location'] as location FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_instrumented_future_duration' ORDER BY location", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Futures", + "version": 0, + "weekStart": "" +} \ No newline at end of file diff --git a/docker/template/grafana-dashboards/gasoline.json b/docker/template/grafana-dashboards/gasoline.json new file mode 100644 index 0000000000..bac8c7b6da --- /dev/null +++ b/docker/template/grafana-dashboards/gasoline.json @@ -0,0 +1,2583 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": 3, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{workflow_name}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_active'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Running Workflows", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 3, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{workflow_name}}", + "meta": {}, + "pluginVersion": "4.10.2", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_sleeping'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Sleeping Workflows", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 1, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{workflow_name}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_dead'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Dead Workflows", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 6, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "({{workflow_name}}) {{error_code}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n Attributes['error_code'] as error_code,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_workflow_dead'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name, error_code\nORDER BY time", + "refId": "A" + } + ], + "title": "Dead Workflow Errors", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "__auto", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n count(*) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_worker_last_ping'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Workers", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "datacenter_id", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\datacenter_id" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 5, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 4, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{signal_name}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['signal_name'] as signal_name,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_signal_pending'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, signal_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Pending Signals", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "signal_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\signal_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 10, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size", + "value": "" + }, + "yBuckets": { + "mode": "size", + "scale": { + "log": 2, + "type": "log" + }, + "value": "" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "hide": false, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_signal_recv_lag'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Signal Receive Lag", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 24 + }, + "id": 11, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_signal_pull_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY\n Time, le\nORDER BY\n Time, le", + "refId": "A" + } + ], + "title": "Pull Signals Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 32 + }, + "id": 13, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "instant": false, + "legendFormat": "{{worker_instance_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['worker_instance_id'] as worker_instance_id,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_last_pull_workflows_duration'\n AND ResourceAttributes['cluster_id'] LIKE '${cluster_id:regex}'\n AND ResourceAttributes['datacenter_id'] LIKE '${datacenter_id:regex}'\n AND $__timeFilter(TimeUnix)\nGROUP BY time, worker_instance_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Last Pull Workflows Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "worker_instance_id", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\worker_instance_id" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 32 + }, + "id": 14, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "instant": false, + "legendFormat": "{{worker_instance_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['worker_instance_id'] as worker_instance_id,\n max(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_gasoline_last_pull_workflows_history_duration'\n AND ResourceAttributes['cluster_id'] LIKE '${cluster_id:regex}'\n AND ResourceAttributes['datacenter_id'] LIKE '${datacenter_id:regex}'\n AND $__timeFilter(TimeUnix)\nGROUP BY time, worker_instance_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Last Pull Workflows History Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "worker_instance_id", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\worker_instance_id" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 40 + }, + "id": 23, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_pull_workflows_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Pull Workflows Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 40 + }, + "id": 24, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_pull_workflows_history_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Pull Workflows History Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 48 + }, + "id": 16, + "panels": [], + "title": "Steps", + "type": "row" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 49 + }, + "id": 12, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_activity_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Activity Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 49 + }, + "id": 9, + "interval": "15s", + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "legendFormat": "{{activity_name}}: {{error_code}}", + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['activity_name'] as activity_name,\n Attributes['error_code'] as error_code,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_gasoline_activity_errors'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, activity_name, error_code\nORDER BY time", + "refId": "A" + } + ], + "title": "Activity Error Rate", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "activity_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\activity_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 58 + }, + "id": 21, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_loop_iteration_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Loop Upsert Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ev/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 58 + }, + "id": 25, + "interval": "15s", + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "legendFormat": "{{workflow_name}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n Attributes['workflow_name'] as workflow_name,\n sum(Count) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_histogram\nWHERE MetricName = 'rivet_gasoline_loop_iteration_duration'\n AND Attributes['workflow_name'] LIKE '${workflow_name:regex}'\n AND ResourceAttributes['cluster_id'] LIKE '${cluster_id:regex}'\n AND ResourceAttributes['datacenter_id'] LIKE '${datacenter_id:regex}'\n AND $__timeFilter(TimeUnix)\nGROUP BY time, workflow_name\nORDER BY time", + "refId": "A" + } + ], + "title": "Loop Events Per Second", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "workflow_name", + "emptyValue": "zero", + "rowField": "time", + "valueField": "value" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "time\\workflow_name" + } + ], + "fields": {} + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 67 + }, + "id": 17, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_message_send_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Message Send Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 67 + }, + "id": 20, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_signal_send_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Signal Send Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 76 + }, + "id": 22, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_find_workflows_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Find Workflows Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 76 + }, + "id": 19, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "meta": {}, + "pluginVersion": "4.10.1", + "queryType": "table", + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_gasoline_workflow_dispatch_duration'\n AND $__conditionalAll(Attributes['workflow_name'], $workflow_name)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Sub Workflow Dispatch Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "5s", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY cluster_id", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY cluster_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY datacenter_id", + "includeAll": true, + "label": "Datacenter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_gasoline_worker_last_ping' ORDER BY datacenter_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['workflow_name'] as workflow_name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_gasoline_signal_recv_lag' ORDER BY workflow_name", + "includeAll": true, + "label": "Workflow Name", + "multi": true, + "name": "workflow_name", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['workflow_name'] as workflow_name FROM otel.otel_metrics_histogram WHERE MetricName = 'rivet_gasoline_signal_recv_lag' ORDER BY workflow_name", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Gasoline", + "uid": "636d22f9-d18f-4086-8b45-7c50886a105c", + "version": 1, + "weekStart": "" +} diff --git a/docker/template/grafana-dashboards/guard.json b/docker/template/grafana-dashboards/guard.json new file mode 100644 index 0000000000..fb657d441b --- /dev/null +++ b/docker/template/grafana-dashboards/guard.json @@ -0,0 +1,1150 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 115, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 10, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_route_cache_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Route Cache Size", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 11, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_rate_limiter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Rate Limiters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 12, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_in_flight_counter_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "In-Flight Counters", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 8 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_tcp_connection_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active TCP Connections", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 8 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_tcp_connection'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "TCP Connection Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 8 + }, + "id": 1, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_tcp_connection_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "TCP Connection Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 16 + }, + "id": 7, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_guard_proxy_request_pending'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Proxy Requests", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "req/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 16 + }, + "id": 8, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_guard_proxy_request'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Proxy Request Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 16 + }, + "id": 9, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_proxy_request_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Proxy Request Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 24 + }, + "id": 6, + "options": { + "calculate": false, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_guard_resolve_route_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Resolve Route Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "description": "", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY cluster_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "description": "", + "includeAll": true, + "label": "Dataceter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY datacenter_id", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "description": "", + "includeAll": true, + "label": "Server ID", + "multi": true, + "name": "server_id", + "options": [], + "query": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_guard_tcp_connection_pending' ORDER BY server_id", + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Rivet Guard", + "uid": "cen785ige8fswd", + "version": 1, + "weekStart": "" +} diff --git a/docker/template/grafana-dashboards/tokio.json b/docker/template/grafana-dashboards/tokio.json new file mode 100644 index 0000000000..efa5e4b49f --- /dev/null +++ b/docker/template/grafana-dashboards/tokio.json @@ -0,0 +1,1009 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": 81, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 24, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_global_queue_depth'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Global Queue Depth", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 27, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_worker_local_queue_depth'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Worker Queue Depth", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 11, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_tokio_task_poll_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Task Poll Times", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 26, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_worker_overflow_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Worker Overflow Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 23, + "interval": "15s", + "options": { + "calculate": false, + "calculation": { + "xBuckets": { + "mode": "size" + } + }, + "cellGap": 0, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "RdBu", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": true + }, + "yAxis": { + "axisPlacement": "left", + "max": "60", + "min": 0, + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "range": true, + "rawSql": "WITH\n $__timeInterval(TimeUnix) as time_bucket,\n arrayJoin(arrayEnumerate(BucketCounts)) AS idx,\n ExplicitBounds AS bounds\nSELECT\n time_bucket as Time,\n bounds[idx+1] AS le,\n sum(BucketCounts[idx]) AS count\nFROM otel.otel_metrics_histogram\nWHERE\n MetricName = 'rivet_future_schedule_duration'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY Time, le\nORDER BY Time, le", + "refId": "A" + } + ], + "title": "Future Schedule Duration", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "le", + "emptyValue": "zero", + "rowField": "Time", + "valueField": "count" + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [ + { + "destinationType": "time", + "targetField": "Time\\le" + } + ], + "fields": {} + } + } + ], + "type": "heatmap" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 25, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_thread_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Thread Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "tasks/s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 28, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n sum(Value) / $__interval_ms * 1000 as value\nFROM otel.otel_metrics_sum\nWHERE MetricName = 'rivet_tokio_task'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Task Spawn Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 0.1, + "axisSoftMin": 0, + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 24 + }, + "id": 29, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": false, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorMode": "code", + "editorType": "sql", + "format": 1, + "instant": false, + "legendFormat": "{{datacenter_id}} - {{server_id}}", + "range": true, + "rawSql": "SELECT\n $__timeInterval(TimeUnix) as time,\n ResourceAttributes['datacenter_id'] as datacenter_id,\n ResourceAttributes['server_id'] as server_id,\n avg(Value) as value\nFROM otel.otel_metrics_gauge\nWHERE MetricName = 'rivet_tokio_active_task_count'\n AND $__conditionalAll(ResourceAttributes['cluster_id'], $cluster_id)\n AND $__conditionalAll(ResourceAttributes['datacenter_id'], $datacenter_id)\n AND $__conditionalAll(ResourceAttributes['server_id'], $server_id)\n AND $__conditionalAll(Attributes['pool_type'], $pool_type)\n AND $__timeFilter(TimeUnix)\nGROUP BY time, datacenter_id, server_id\nORDER BY time", + "refId": "A" + } + ], + "title": "Active Tasks", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "5s", + "schemaVersion": 40, + "templating": { + "list": [ + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY cluster_id", + "description": "", + "includeAll": true, + "label": "Cluster ID", + "multi": true, + "name": "cluster_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['cluster_id'] as cluster_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY cluster_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY datacenter_id", + "description": "", + "includeAll": true, + "label": "Dataceter ID", + "multi": true, + "name": "datacenter_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['datacenter_id'] as datacenter_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY datacenter_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY server_id", + "description": "", + "includeAll": true, + "label": "Server ID", + "multi": true, + "name": "server_id", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT ResourceAttributes['server_id'] as server_id FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY server_id", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT Attributes['pool_type'] as pool_type FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY pool_type", + "includeAll": true, + "label": "Pool", + "multi": true, + "name": "pool_type", + "options": [], + "query": { + "qryType": 1, + "rawSql": "SELECT DISTINCT Attributes['pool_type'] as pool_type FROM otel.otel_metrics_gauge WHERE MetricName = 'rivet_tokio_thread_count' ORDER BY pool_type", + "refId": "ClickHouseVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Tokio", + "uid": "636d22f9-d18f-4086-8b45-7c50886a105d", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/docker/template/grafana-dashboards/traces.json b/docker/template/grafana-dashboards/traces.json new file mode 100644 index 0000000000..64f6b552c9 --- /dev/null +++ b/docker/template/grafana-dashboards/traces.json @@ -0,0 +1,979 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 21, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 9, + "panels": [], + "title": "Traces", + "type": "row" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "bars", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 0, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 1 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-traces" + }, + "editorType": "sql", + "format": 0, + "meta": { + "builderOptions": { + "aggregates": [ + { + "aggregateType": "count", + "column": "" + } + ], + "columns": [ + { + "hint": "time", + "name": "Timestamp", + "type": "DateTime64(9)" + } + ], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "hint": "time", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "ServiceName" + ], + "limit": 10000, + "mode": "trend", + "orderBy": [], + "queryType": "timeseries", + "table": "otel_traces" + } + }, + "pluginVersion": "4.0.6", + "queryType": "timeseries", + "rawSql": "SELECT\r\n $__timeInterval(Timestamp) as time,\r\n ServiceName,\r\n count() as ` `\r\nFROM otel.otel_traces\r\nWHERE\r\n ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )\r\n AND $__conditionalAll(ServiceName, $service_name)\r\n AND $__conditionalAll(SpanName, $span_name)\r\n AND (($ray_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['ray_id'], $ray_id))\r\n AND (($workflow_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['workflow_id'], $workflow_id))\r\nGROUP BY ServiceName, time\r\nORDER BY time ASC\r\nLIMIT 100000\r\n", + "refId": "A" + } + ], + "title": "Traces per Service", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Trace ID" + }, + "properties": [ + { + "id": "custom.width", + "value": 77 + }, + { + "id": "links", + "value": [ + { + "title": "__value.raw", + "url": "/d/8klBUGfVk/otel-traces?${__url_time_range}&${service_name:queryparam}&var-trace_id=${__value.raw}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Service Name" + }, + "properties": [ + { + "id": "custom.width", + "value": 130 + }, + { + "id": "links", + "value": [ + { + "title": "__value.raw", + "url": "/d/8klBUGfVk/otel-traces?${__url_time_range}&${trace_id:queryparam}&var-serviceName=${__value.raw}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Duration" + }, + "properties": [ + { + "id": "unit", + "value": "ms" + }, + { + "id": "custom.cellOptions", + "value": { + "mode": "lcd", + "type": "gauge", + "valueDisplayMode": "text" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "timestamp" + }, + "properties": [ + { + "id": "custom.width", + "value": 216 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Service Tags" + }, + "properties": [ + { + "id": "custom.inspect", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "timestamp" + }, + "properties": [ + { + "id": "custom.width", + "value": 248 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "timestamp" + }, + "properties": [ + { + "id": "custom.width", + "value": 234 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": " " + }, + "properties": [ + { + "id": "custom.width", + "value": 49 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Span Name" + }, + "properties": [ + { + "id": "custom.width", + "value": 140 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Ts" + }, + "properties": [ + { + "id": "custom.width", + "value": 168 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "URI/workflow_id/actor_id" + }, + "properties": [ + { + "id": "custom.width", + "value": 920 + } + ] + } + ] + }, + "gridPos": { + "h": 13, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 4, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Duration" + } + ] + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorType": "sql", + "format": 1, + "meta": { + "builderOptions": { + "columns": [], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "queryType": "table", + "table": "otel_traces" + } + }, + "pluginVersion": "4.9.0", + "queryType": "table", + "rawSql": "SELECT\r\n (argMin(StatusCode, Timestamp) = 'Error' ? '⚠️' : '') as ` `,\r\n min(Timestamp) as Ts,\r\n TraceId as `Trace ID`,\r\n argMin(ServiceName, Timestamp) as `Service Name`,\r\n argMin(SpanName, Timestamp) as `Span Name`,\r\n argMin(coalesce(NULLIF(SpanAttributes['uri'], ''), NULLIF(SpanAttributes['workflow_id'], ''), SpanAttributes['actor_id']), Timestamp) as `URI/workflow_id/actor_id`,\r\n divide(max(Duration), 1000000) as Duration\r\nFROM otel.otel_traces\r\nWHERE\r\n $__conditionalAll(ServiceName, $service_name)\r\n AND $__conditionalAll(SpanName, $span_name)\r\n AND (($ray_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['ray_id'], $ray_id))\r\n AND (($workflow_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['workflow_id'], $workflow_id))\r\n AND ServiceName != 'loadgenerator'\r\n AND ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )\r\nGROUP BY TraceId\r\nORDER BY Duration DESC\r\nLIMIT 100\r\n", + "refId": "A" + } + ], + "title": "Traces", + "type": "table" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, + "gridPos": { + "h": 17, + "w": 24, + "x": 0, + "y": 23 + }, + "id": 6, + "options": { + "spanFilters": { + "criticalPathOnly": false, + "matchesOnly": false, + "serviceNameOperator": "=", + "spanNameOperator": "=" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "builderOptions": { + "columns": [ + { + "hint": "trace_id", + "name": "TraceId" + }, + { + "hint": "trace_span_id", + "name": "SpanId" + }, + { + "hint": "trace_parent_span_id", + "name": "ParentSpanId" + }, + { + "hint": "trace_service_name", + "name": "ServiceName" + }, + { + "hint": "trace_operation_name", + "name": "SpanName" + }, + { + "hint": "time", + "name": "Timestamp" + }, + { + "hint": "trace_duration_time", + "name": "Duration" + }, + { + "hint": "trace_tags", + "name": "SpanAttributes" + }, + { + "hint": "trace_service_tags", + "name": "ResourceAttributes" + }, + { + "hint": "trace_status_code", + "name": "StatusCode" + } + ], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "hint": "time", + "key": "", + "operator": "WITH IN DASHBOARD TIME RANGE", + "type": "datetime" + }, + { + "condition": "AND", + "filterType": "custom", + "hint": "trace_duration_time", + "key": "", + "operator": ">", + "type": "UInt64", + "value": 0 + }, + { + "condition": "AND", + "filterType": "custom", + "hint": "trace_service_name", + "key": "", + "operator": "IS ANYTHING", + "type": "string", + "value": "" + } + ], + "limit": 1000, + "meta": { + "isTraceIdMode": true, + "otelEnabled": true, + "otelVersion": "latest", + "traceDurationUnit": "nanoseconds", + "traceId": "${trace_id}" + }, + "mode": "list", + "orderBy": [ + { + "default": true, + "dir": "DESC", + "hint": "time", + "name": "" + }, + { + "default": true, + "dir": "DESC", + "hint": "trace_duration_time", + "name": "" + } + ], + "queryType": "traces", + "table": "otel_traces" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-traces" + }, + "editorType": "builder", + "format": 3, + "meta": { + "builderOptions": { + "columns": [], + "database": "", + "limit": 100, + "mode": "list", + "queryType": "table", + "table": "" + } + }, + "pluginVersion": "4.0.6", + "queryType": "traces", + "rawSql": "WITH\n\t(SELECT min(Start) FROM otel.otel_traces_trace_id_ts WHERE $__conditionalAll(TraceId, $trace_id)) as trace_start,\n\t(SELECT max(End) + 1 FROM otel.otel_traces_trace_id_ts WHERE $__conditionalAll(TraceId, $trace_id)) as trace_end\nSELECT\n\tTraceId as traceID,\n\tSpanId as spanID,\n\tParentSpanId as parentSpanID,\n\tServiceName as serviceName,\n\tSpanName as operationName, Timestamp as startTime,\n\tmultiply(Duration, 0.000001) as duration,\n\tarrayMap(key -> map('key', key, 'value', SpanAttributes[key]), mapKeys(SpanAttributes)) as tags,\n\tarrayMap(key -> map('key', key, 'value', ResourceAttributes[key]), mapKeys(ResourceAttributes)) as serviceTags,\n\tarrayMap((name, timestamp, attributes) -> tuple(name, toString(multiply(toUnixTimestamp64Nano(timestamp), 0.000001)), arrayMap( key -> map('key', key, 'value', attributes[key]), mapKeys(attributes)))::Tuple(name String, timestamp String, fields Array(Map(String, String))), `Events.Name`, `Events.Timestamp`, `Events.Attributes`) AS logs,\n\tarrayMap((traceID, spanID, attributes) -> tuple(traceID, spanID, arrayMap(key -> map('key', key, 'value', attributes[key]), mapKeys(attributes)))::Tuple(traceID String, spanID String, tags Array(Map(String, String))), `Links.TraceId`, `Links.SpanId`, `Links.Attributes`) AS references\nFROM otel.otel_traces\nWHERE\n\t$__conditionalAll(traceID, $trace_id) AND startTime >= trace_start AND startTime <= trace_end AND ( Duration > 0 )\nORDER BY Timestamp DESC, Duration DESC\nLIMIT 1000", + "refId": "A" + } + ], + "title": "Trace Details", + "type": "traces" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "bars", + "fillOpacity": 24, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 8, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-traces" + }, + "editorType": "sql", + "format": 0, + "meta": { + "builderOptions": { + "aggregates": [ + { + "aggregateType": "count", + "column": "" + } + ], + "columns": [ + { + "hint": "time", + "name": "Timestamp", + "type": "DateTime64(9)" + } + ], + "database": "otel", + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "hint": "time", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "ServiceName" + ], + "limit": 10000, + "mode": "trend", + "orderBy": [], + "queryType": "timeseries", + "table": "otel_traces" + } + }, + "pluginVersion": "4.0.6", + "queryType": "timeseries", + "rawSql": "SELECT\r\n $__timeInterval(Timestamp) as time,\r\n count(*) as ` `,\r\n ServiceName\r\nFROM otel.otel_traces\r\nWHERE\r\n $__conditionalAll(TraceId, $trace_id)\r\n AND ( Timestamp >= $__fromTime AND Timestamp <= $__toTime )\r\n AND $__conditionalAll(ServiceName, $service_name)\r\n AND $__conditionalAll(SpanName, $span_name)\r\n AND (($ray_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['ray_id'], $ray_id)\r\n AND (($workflow_id, NULL).1 = 'All' ? true : $__conditionalAll(SpanAttributes['workflow_id'], $workflow_id))\r\n AND StatusCode IN ('Error', 'STATUS_CODE_ERROR')\r\n AND ServiceName != 'loadgenerator' GROUP BY ServiceName, time\r\nORDER BY time ASC\r\nLIMIT 100000", + "refId": "A" + } + ], + "title": "Error rates", + "type": "timeseries" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 49 + }, + "id": 10, + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 61 + }, + "id": 11, + "options": { + "dedupStrategy": "none", + "enableInfiniteScrolling": false, + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": true, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "pluginVersion": "11.5.2", + "targets": [ + { + "builderOptions": { + "columns": [ + { + "hint": "time", + "name": "Timestamp", + "type": "DateTime64(9)" + }, + { + "hint": "log_level", + "name": "SeverityText", + "type": "LowCardinality(String)" + }, + { + "hint": "log_message", + "name": "Body", + "type": "String" + } + ], + "database": "otel", + "filters": [], + "limit": 1000, + "meta": { + "logMessageLike": "", + "otelVersion": "latest" + }, + "mode": "list", + "orderBy": [], + "queryType": "logs", + "table": "otel_logs" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "editorType": "builder", + "format": 2, + "pluginVersion": "4.0.6", + "rawSql": "SELECT Timestamp as timestamp, Body as body, SeverityText as level FROM \"otel\".\"otel_logs\" LIMIT 1000", + "refId": "A" + } + ], + "title": "Trace Logs", + "type": "logs" + } + ], + "title": "Logs", + "type": "row" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "ClickHouse", + "value": "ClickHouse" + }, + "includeAll": false, + "label": "ClickHouse instance", + "name": "datasource", + "options": [], + "query": "grafana-clickhouse-datasource", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT ServiceName FROM otel.otel_traces", + "includeAll": true, + "label": "Service Name", + "multi": true, + "name": "service_name", + "options": [], + "query": "SELECT DISTINCT ServiceName FROM otel.otel_traces", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT TraceId FROM otel.otel_traces WHERE ParentSpanId = '' LIMIT 100", + "includeAll": true, + "label": "Trace ID", + "name": "trace_id", + "options": [], + "query": "SELECT DISTINCT TraceId FROM otel.otel_traces WHERE ParentSpanId = '' LIMIT 100", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT SpanName FROM otel.otel_traces WHERE $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "description": "", + "includeAll": true, + "label": "Span", + "multi": true, + "name": "span_name", + "options": [], + "query": "SELECT DISTINCT SpanName FROM otel.otel_traces WHERE $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "allValue": "'All'", + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT SpanAttributes['ray_id'] FROM otel.otel_traces WHERE SpanAttributes['ray_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "description": "", + "includeAll": true, + "label": "Ray ID", + "multi": true, + "name": "ray_id", + "options": [], + "query": "SELECT DISTINCT SpanAttributes['ray_id'] FROM otel.otel_traces WHERE SpanAttributes['ray_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "refresh": 1, + "regex": "", + "type": "query" + }, + { + "allValue": "'All'", + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse" + }, + "definition": "SELECT DISTINCT SpanAttributes['workflow_id'] FROM otel.otel_traces WHERE SpanAttributes['workflow_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "description": "", + "includeAll": true, + "label": "Workflow ID", + "multi": true, + "name": "workflow_id", + "options": [], + "query": "SELECT DISTINCT SpanAttributes['workflow_id'] FROM otel.otel_traces WHERE SpanAttributes['workflow_id'] != '' AND $__conditionalAll(ServiceName, $service_name) LIMIT 1000;", + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "America/Los_Angeles", + "title": "Traces", + "uid": "8klBUGfVk", + "version": 2, + "weekStart": "" +} diff --git a/docker/template/package.json b/docker/template/package.json new file mode 100644 index 0000000000..0756bffdc7 --- /dev/null +++ b/docker/template/package.json @@ -0,0 +1,23 @@ +{ + "name": "@rivetkit/docker-template", + "version": "1.0.0", + "description": "Docker compose templating for Rivet", + "main": "dist/main.js", + "private": true, + "scripts": { + "start": "tsx src/main.ts", + "check-types": "tsc --noEmit" + }, + "dependencies": { + "@types/js-yaml": "^4.0.9", + "js-yaml": "^4.1.0", + "tsx": "^4.0.0" + }, + "devDependencies": { + "@types/node": "^20.19.9", + "typescript": "^5.0.0" + }, + "engines": { + "node": ">=18.0.0" + } +} diff --git a/docker/template/src/config.ts b/docker/template/src/config.ts new file mode 100644 index 0000000000..271e186731 --- /dev/null +++ b/docker/template/src/config.ts @@ -0,0 +1,104 @@ +export interface Datacenter { + name: string; + id: number; // u16 + peer_id: number; // u64 + engines: number; + runners: number; +} + +export interface TemplateConfig { + networkMode: "bridge" | "host"; + datacenters: Datacenter[]; +} + +// TODO: Add support for splitting up engine/guard services +export const TEMPLATES: Record = { + dev: { + networkMode: "bridge", + datacenters: [ + { + name: "local", + id: 1, + peer_id: 1, + engines: 1, + runners: 1, + }, + ], + }, + "dev-multinode": { + networkMode: "bridge", + datacenters: [ + { + name: "local", + id: 1, + peer_id: 1, + engines: 3, + runners: 3, + }, + ], + }, + "dev-multidc": { + networkMode: "bridge", + datacenters: [ + { + name: "dc-a", + id: 1, + peer_id: 1, + engines: 1, + runners: 1, + }, + { + name: "dc-b", + id: 2, + peer_id: 2, + engines: 1, + runners: 1, + }, + { + name: "dc-c", + id: 3, + peer_id: 3, + engines: 1, + runners: 1, + }, + ], + }, + "dev-multidc-multinode": { + networkMode: "bridge", + datacenters: [ + { + name: "dc-a", + id: 1, + peer_id: 1, + engines: 3, + runners: 3, + }, + { + name: "dc-b", + id: 2, + peer_id: 2, + engines: 3, + runners: 3, + }, + { + name: "dc-c", + id: 3, + peer_id: 3, + engines: 3, + runners: 3, + }, + ], + }, + "dev-host": { + networkMode: "host", + datacenters: [ + { + name: "local", + id: 1, + peer_id: 1, + engines: 1, + runners: 1, + }, + ], + }, +}; diff --git a/docker/template/src/context.ts b/docker/template/src/context.ts new file mode 100644 index 0000000000..af44bc591e --- /dev/null +++ b/docker/template/src/context.ts @@ -0,0 +1,206 @@ +import * as fs from "fs"; +import * as path from "path"; +import type { TemplateConfig } from "./config"; + +export const CORE_NETWORK_NAME = "rivet-core-network"; +// If there's only one datacenter +export const SIMPLE_NETWORK_NAME = "rivet-network"; + +export class TemplateContext { + config: TemplateConfig; + private outputDir: string; + + constructor(config: TemplateConfig, outputDir: string) { + this.config = config; + this.outputDir = outputDir; + } + + getDatacenter(dcId: string) { + const datacenter = this.config.datacenters.find((dc) => dc.name === dcId); + if (!datacenter) + throw new Error(`Datacenter ${dcId} not found in configuration`); + return datacenter; + } + + writeFile(filePath: string, content: string) { + const fullPath = path.join(this.outputDir, filePath); + const dirPath = path.dirname(fullPath); + + if (!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath, { recursive: true }); + } + + fs.writeFileSync(fullPath, content); + } + + getCoreServicePath(service: string): string { + // If only one datacenter, put core services at root level + if (this.config.datacenters.length === 1) { + return service; + } + return `core/${service}`; + } + + getDatacenterServicePath( + service: string, + dcId: string, + nodeIndex?: number, + ): string { + // If only one datacenter, put services at root level + if (!this.shouldIncludeDatacenterInName()) { + if (this.shouldIncludeIndexInPath(service, dcId, nodeIndex)) { + return `${service}/${nodeIndex}`; + } else { + return service; + } + } + + // Multiple datacenters, use datacenter folder + if (this.shouldIncludeIndexInPath(service, dcId, nodeIndex)) { + return `datacenters/${dcId}/${service}/${nodeIndex}`; + } else { + return `datacenters/${dcId}/${service}`; + } + } + + writeCoreServiceFile(service: string, fileName: string, content: string) { + const basePath = this.getCoreServicePath(service); + const filePath = `${basePath}/${fileName}`; + this.writeFile(filePath, content); + } + + writeDatacenterServiceFile( + service: string, + dcId: string, + fileName: string, + content: string, + nodeIndex?: number, + ) { + const basePath = this.getDatacenterServicePath(service, dcId, nodeIndex); + const filePath = `${basePath}/${fileName}`; + this.writeFile(filePath, content); + } + + makeDatabaseFileExec( + service: string, + dcId: string, + fileName: string, + nodeIndex?: number, + ) { + const basePath = this.getDatacenterServicePath(service, dcId, nodeIndex); + const filePath = `${basePath}/${fileName}`; + const fullPath = path.join(this.outputDir, filePath); + + fs.chmodSync(fullPath, 0o755); + } + + shouldIncludeDatacenterInName(): boolean { + return this.config.datacenters.length > 1; + } + + shouldIncludeIndexInName( + service: string, + dcId: string, + index?: number, + ): boolean { + if (index === undefined) { + return false; + } + + const datacenter = this.getDatacenter(dcId); + + // Determine max instances based on service type + let maxInstances = 1; + if (service === "rivet-engine" || service === "rivet-shell") { + maxInstances = datacenter.engines; + } else if (service === "runner") { + maxInstances = datacenter.runners; + } + // postgres always has 1 instance per datacenter + + return maxInstances > 1; + } + + shouldIncludeIndexInPath( + service: string, + dcId: string, + nodeIndex?: number, + ): boolean { + if (nodeIndex === undefined) { + return false; + } + + const datacenter = this.getDatacenter(dcId); + + // Determine max instances based on service type + let maxInstances = 1; + if (service === "rivet-engine") { + maxInstances = datacenter.engines; + } else if (service === "runner") { + maxInstances = datacenter.runners; + } + // postgres always has 1 instance per datacenter + + return maxInstances > 1; + } + + shouldIncludeIndexInVolume( + service: string, + dcId: string, + index?: number, + ): boolean { + if (index === undefined) { + return false; + } + + const datacenter = this.getDatacenter(dcId); + + // Determine max instances based on service type + let maxInstances = 1; + if (service === "runner") { + maxInstances = datacenter.runners; + } + // postgres always has 1 instance per datacenter + + return maxInstances > 1; + } + + getDatacenterNetworkName(dcId: string): string { + // If only one datacenter, use simpler network name + if (!this.shouldIncludeDatacenterInName()) { + return SIMPLE_NETWORK_NAME; + } + return `rivet-network-${dcId}`; + } + + getServiceName(service: string, dcId: string, index?: number): string { + // Build service name based on conditions + let name = service; + if (this.shouldIncludeDatacenterInName()) { + name += `-${dcId}`; + } + if (this.shouldIncludeIndexInName(service, dcId, index)) { + name += `-${index}`; + } + return name; + } + + // Returns the hostname to use for service-to-service communication. + // In host networking, services communicate via 127.0.0.1; otherwise use the service DNS name. + getServiceHost(service: string, dcId: string, index?: number): string { + if ((this.config as any).networkMode === "host") return "127.0.0.1"; + return this.getServiceName(service, dcId, index); + } + + getVolumeName(service: string, dcId: string, index?: number): string { + // Build volume name based on conditions + let name = `${service}-data`; + if (this.shouldIncludeDatacenterInName()) { + name += `-${dcId}`; + } + if (this.shouldIncludeIndexInVolume(service, dcId, index)) { + name += `-${index}`; + } + return name; + } +} diff --git a/docker/template/src/docker-compose.ts b/docker/template/src/docker-compose.ts new file mode 100644 index 0000000000..1cdd55d105 --- /dev/null +++ b/docker/template/src/docker-compose.ts @@ -0,0 +1,359 @@ +import { CORE_NETWORK_NAME, TemplateContext } from "./context"; +import * as yaml from "js-yaml"; + +export function generateDockerCompose(context: TemplateContext) { + const config = context.config; + + // Services configuration + const services: Record = {}; + const networks: Record = {}; + const volumes: Record = {}; + + const allDcEnginePeerNetworkNames = config.datacenters.map( + (datacenter) => + `${context.getDatacenterNetworkName(datacenter.name)}-engine-peer`, + ); + const allDcToCoreNetworkNames = config.datacenters.map( + (datacenter) => + `${context.getDatacenterNetworkName(datacenter.name)}-to-core`, + ); + + // Core services + networks[CORE_NETWORK_NAME] = { + driver: "bridge", + }; + + // ClickHouse + services["clickhouse"] = { + restart: "unless-stopped", + image: "clickhouse/clickhouse-server:25.1.5", + volumes: [ + "clickhouse-data:/var/lib/clickhouse", + `./${context.getCoreServicePath("clickhouse")}/config.xml:/etc/clickhouse-server/config.d/config.xml`, + `./${context.getCoreServicePath("clickhouse")}/users.xml:/etc/clickhouse-server/users.d/users.xml`, + `./${context.getCoreServicePath("clickhouse")}/client-config.xml:/etc/clickhouse-client/config.xml`, + `./${context.getCoreServicePath("clickhouse")}/init:/docker-entrypoint-initdb.d`, + ], + environment: [ + //Run migrations on startup + "CLICKHOUSE_ALWAYS_RUN_INITDB_SCRIPTS=true", + "CLICKHOUSE_USER=default", + "CLICKHOUSE_PASSWORD=default", + "CLICKHOUSE_HTTP_PORT=9300", + "CLICKHOUSE_TCP_PORT=9301", + ], + networks: [...allDcToCoreNetworkNames, CORE_NETWORK_NAME], + healthcheck: { + test: [ + "CMD", + "clickhouse-client", + "--host", + "127.0.0.1", + "--port", + "9301", + "--user", + "system", + "--password", + "default", + "--query", + "SELECT 1", + ], + interval: "2s", + timeout: "10s", + retries: 10, + }, + }; + volumes["clickhouse-data"] = null; + + // Grafana + services["grafana"] = { + image: "grafana/grafana:11.5.2", + volumes: [ + "grafana-data:/var/lib/grafana", + `./${context.getCoreServicePath("grafana")}/grafana.ini:/etc/grafana/grafana.ini`, + `./${context.getCoreServicePath("grafana")}/provisioning:/etc/grafana/provisioning`, + `./${context.getCoreServicePath("grafana")}/dashboards:/var/lib/grafana/dashboards`, + ], + environment: ["GF_INSTALL_PLUGINS=grafana-clickhouse-datasource"], + ports: ["3100:3000"], + networks: [CORE_NETWORK_NAME], + depends_on: { + clickhouse: { condition: "service_healthy" }, + }, + }; + volumes["grafana-data"] = null; + + // Generate services for each datacenter + config.datacenters.forEach((datacenter, idx) => { + const isPrimary = idx === 0; + + const dcNetworkName = context.getDatacenterNetworkName(datacenter.name); + const dcEnginePeerNetworkName = `${dcNetworkName}-engine-peer`; + const dcToCoreNetworkName = `${dcNetworkName}-to-core`; + + //const natsServiceName = context.getServiceName("nats", datacenter.name); + const vectorServerServiceName = context.getServiceName( + "vector-server", + datacenter.name, + ); + const vectorClientServiceName = context.getServiceName( + "vector-client", + datacenter.name, + ); + const otelCollectorServerServiceName = context.getServiceName( + "otel-collector-server", + datacenter.name, + ); + const otelCollectorClientServiceName = context.getServiceName( + "otel-collector-client", + datacenter.name, + ); + const postgresServiceName = context.getServiceName( + "postgres", + datacenter.name, + ); + const shellServiceName = context.getServiceName( + "rivet-shell", + datacenter.name, + ); + + networks[dcNetworkName] = { + driver: "bridge", + }; + + networks[dcEnginePeerNetworkName] = { + driver: "bridge", + }; + + networks[dcToCoreNetworkName] = { + driver: "bridge", + }; + + //services[natsServiceName] = { + // restart: "unless-stopped", + // image: "nats:2.10.22-scratch", + // networks: [dcNetworkName], + // ports: isPrimary ? [`4222:4222`] : undefined, + // healthcheck: { + // test: ["CMD", "nats-server", "--health"], + // interval: "2s", + // timeout: "10s", + // retries: 10, + // }, + //}; + + const postgresVolumeName = context.getVolumeName( + "postgres", + datacenter.name, + ); + services[postgresServiceName] = { + restart: "unless-stopped", + image: "postgres:16-alpine", + environment: [ + "POSTGRES_USER=postgres", + "POSTGRES_PASSWORD=postgres", + "POSTGRES_DB=postgres", + ], + volumes: [ + `./${context.getDatacenterServicePath("postgres", datacenter.name)}/init-db.sh:/docker-entrypoint-initdb.d/init-db.sh`, + `${postgresVolumeName}:/var/lib/postgresql/data`, + ], + ports: isPrimary ? [`5432:5432`] : undefined, + healthcheck: { + test: ["CMD-SHELL", "pg_isready -U postgres -d postgres"], + interval: "2s", + timeout: "10s", + retries: 10, + }, + networks: [dcNetworkName], + }; + volumes[postgresVolumeName] = null; + + services[shellServiceName] = { + build: { + context: "../..", + dockerfile: "docker/universal/Dockerfile", + target: "engine-full", + }, + platform: "linux/amd64", + restart: "unless-stopped", + command: "sleep infinity", + stop_grace_period: "0s", + depends_on: { + //[natsServiceName]: { condition: "service_healthy" }, + [postgresServiceName]: { condition: "service_healthy" }, + }, + volumes: [ + `./${context.getDatacenterServicePath("rivet-engine", datacenter.name, 0)}/config.jsonc:/etc/rivet/config.jsonc:ro`, + ], + networks: [ + dcNetworkName, + dcToCoreNetworkName, + ...allDcEnginePeerNetworkNames, + ], + }; + + services[vectorServerServiceName] = { + restart: "unless-stopped", + image: "timberio/vector:0.48.0-distroless-static", + command: "-C /etc/vector", + volumes: [ + `vector-server-data-${datacenter.name}:/var/lib/vector`, + `./${context.getDatacenterServicePath("vector-server", datacenter.name)}:/etc/vector`, + ], + networks: [dcNetworkName, dcToCoreNetworkName], + depends_on: { + clickhouse: { condition: "service_healthy" }, + }, + }; + volumes[`vector-server-data-${datacenter.name}`] = null; + + services[vectorClientServiceName] = { + restart: "unless-stopped", + image: "timberio/vector:0.48.0-distroless-static", + command: "-C /etc/vector", + volumes: [ + `vector-client-data-${datacenter.name}:/var/lib/vector`, + `./${context.getDatacenterServicePath("vector-client", datacenter.name)}:/etc/vector`, + ], + networks: [dcNetworkName], + depends_on: { + [vectorServerServiceName]: { condition: "service_started" }, + }, + }; + volumes[`vector-client-data-${datacenter.name}`] = null; + + services[otelCollectorServerServiceName] = { + image: "otel/opentelemetry-collector-contrib:latest", + restart: "unless-stopped", + command: "--config=/etc/otel/config.yaml", + volumes: [ + `./${context.getDatacenterServicePath("otel-collector-server", datacenter.name)}/config.yaml:/etc/otel/config.yaml:ro`, + ], + environment: ["CLICKHOUSE_PASSWORD=default"], + depends_on: { + clickhouse: { condition: "service_healthy" }, + }, + networks: [dcNetworkName, dcToCoreNetworkName], + }; + + services[otelCollectorClientServiceName] = { + image: "otel/opentelemetry-collector-contrib:latest", + restart: "unless-stopped", + command: "--config=/etc/otel/config.yaml", + volumes: [ + `./${context.getDatacenterServicePath("otel-collector-client", datacenter.name)}/config.yaml:/etc/otel/config.yaml:ro`, + ], + depends_on: { + [otelCollectorServerServiceName]: { condition: "service_started" }, + }, + networks: [dcNetworkName], + }; + + for (let i = 0; i < datacenter.engines; i++) { + const serviceName = context.getServiceName( + "rivet-engine", + datacenter.name, + i, + ); + + services[serviceName] = { + build: { + context: "../..", + dockerfile: "docker/universal/Dockerfile", + target: "engine-full", + }, + platform: "linux/amd64", + restart: "unless-stopped", + command: "/usr/bin/rivet-engine start", + environment: [ + "RUST_LOG_ANSI_COLOR=1", + "RIVET_OTEL_ENABLED=1", + "RIVET_OTEL_SAMPLER_RATIO=1", + `RIVET_OTEL_GRPC_ENDPOINT=http://${context.getServiceHost("otel-collector-client", datacenter.name)}:4317`, + // "RUST_LOG=debug,hyper=info", + ], + stop_grace_period: "0s", + depends_on: { + //[natsServiceName]: { condition: "service_healthy" }, + [vectorClientServiceName]: { + condition: "service_started", + }, + [otelCollectorClientServiceName]: { + condition: "service_started", + }, + [postgresServiceName]: { condition: "service_healthy" }, + }, + volumes: [ + `./${context.getDatacenterServicePath("rivet-engine", datacenter.name, i)}/config.jsonc:/etc/rivet/config.jsonc:ro`, + ], + networks: [ + dcNetworkName, + dcToCoreNetworkName, + ...allDcEnginePeerNetworkNames, + ], + ports: isPrimary && i === 0 ? [`6420:6420`] : undefined, + healthcheck: { + test: ["CMD", "curl", "-f", "http://127.0.0.1:6421/health"], + interval: "2s", + timeout: "10s", + retries: 10, + start_period: "30s", + }, + }; + } + + for (let i = 0; i < datacenter.runners; i++) { + const serviceName = context.getServiceName("runner", datacenter.name, i); + const engineServiceName = context.getServiceName( + "rivet-engine", + datacenter.name, + 0, + ); + + services[serviceName] = { + build: { + context: "../..", + dockerfile: "sdks/typescript/test-runner/Dockerfile", + }, + platform: "linux/amd64", + restart: "unless-stopped", + environment: [ + `RIVET_ENDPOINT=http://${context.getServiceHost("rivet-engine", datacenter.name, 0)}:6420`, + `RUNNER_HOST=${context.getServiceHost("runner", datacenter.name, i)}`, + ], + stop_grace_period: "4s", + ports: isPrimary && i === 0 ? [`5050:5050`] : undefined, + depends_on: { + [engineServiceName]: { + condition: "service_healthy", + }, + }, + networks: [dcNetworkName], + }; + } + }); + + const dockerComposeConfig = { + services, + networks, + volumes, + }; + + // If host networking is requested, set network_mode for all services + if (context.config.networkMode === "host") { + for (const svc of Object.values(dockerComposeConfig.services)) { + // @ts-ignore - mutate dynamic service objects + svc.network_mode = "host"; + // Remove networks field as it's incompatible with host networking + // @ts-ignore + if (svc.networks) delete svc.networks; + // Remove ports since published ports are ignored with host networking + // and produce warnings in Docker Compose output. + // @ts-ignore + if (svc.ports) delete svc.ports; + } + } + + context.writeFile("docker-compose.yml", yaml.dump(dockerComposeConfig)); +} diff --git a/docker/template/src/git.ts b/docker/template/src/git.ts new file mode 100644 index 0000000000..23adde95ea --- /dev/null +++ b/docker/template/src/git.ts @@ -0,0 +1,9 @@ +import { TemplateContext } from "./context"; + +export function generateGitAttributes(context: TemplateContext) { + const gitAttributesContent = `. linguist-generated=true +`; + + context.writeFile(".gitattributes", gitAttributesContent); +} + diff --git a/docker/template/src/main.ts b/docker/template/src/main.ts new file mode 100644 index 0000000000..8500662415 --- /dev/null +++ b/docker/template/src/main.ts @@ -0,0 +1,66 @@ +#!/usr/bin/env node + +import * as fs from "fs"; +import * as path from "path"; + +import { generateCoreClickhouse } from "./services/core/clickhouse"; +import { generateDatacenterVectorServer } from "./services/edge/vector-server"; +import { generateDatacenterOtelCollectorServer } from "./services/edge/otel-collector-server"; +import { generateCoreGrafana } from "./services/core/grafana"; +import { generateDatacenterVectorClient } from "./services/edge/vector-client"; +import { generateDatacenterOtelCollectorClient } from "./services/edge/otel-collector-client"; +import { generateDatacenterPostgres } from "./services/edge/postgres"; +import { generateDatacenterRivetEngine } from "./services/edge/rivet-engine"; +import { generateRunner } from "./services/edge/runner"; +import { generateDockerCompose } from "./docker-compose"; +import { generateReadme } from "./readme"; +import { generateGitAttributes } from "./git"; +import { TEMPLATES, type TemplateConfig } from "./config"; +import { TemplateContext } from "./context"; + +function generateTemplate(templateName: string, config: TemplateConfig) { + const outputDir = path.join(__dirname, "../../", templateName); + + // Remove existing directory if it exists + if (fs.existsSync(outputDir)) { + fs.rmSync(outputDir, { recursive: true, force: true }); + } + + // Create directories + if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir, { recursive: true }); + } + + const context = new TemplateContext(config, outputDir); + + // Generate core services + generateCoreClickhouse(context); + generateCoreGrafana(context); + + // Generate datacenter-specific configurations + for (const datacenter of config.datacenters) { + generateDatacenterPostgres(context, datacenter.name); + generateDatacenterRivetEngine(context, datacenter); + generateDatacenterVectorServer(context, datacenter.name); + generateDatacenterVectorClient(context, datacenter.name); + generateDatacenterOtelCollectorServer(context, datacenter.name); + generateDatacenterOtelCollectorClient(context, datacenter.name); + } + + generateRunner(context); + generateDockerCompose(context); + generateReadme(context, templateName); + generateGitAttributes(context); + + console.log(`✅ Generated Docker Compose template: ${templateName}`); +} + +function main() { + for (const [templateName, template] of Object.entries(TEMPLATES)) { + generateTemplate(templateName, template); + } +} + +if (require.main === module) { + main(); +} diff --git a/docker/template/src/readme.ts b/docker/template/src/readme.ts new file mode 100644 index 0000000000..7184b33499 --- /dev/null +++ b/docker/template/src/readme.ts @@ -0,0 +1,98 @@ +import { TemplateContext } from "./context"; + +export function generateReadme(context: TemplateContext, templateName: string) { + const config = context.config; + + const ports = { + rivetEngineGuard: 6420, + runner: 5050, + //nats: 4222, + postgres: 5432, + clickhouseHttp: 9300, + clickhouseNative: 9301, + otelGrpc: 4317, + otelHttp: 4318, + }; + + const readmeContent = `# ${templateName} - Auto-generated Docker Compose Template + +> ! **Auto-generated**: This directory and its contents are automatically generated by \`docker/template/\`. Do not edit these files directly as your changes will be overwritten. + +## Overview + +This Docker Compose configuration provides a complete development environment for Rivet with the following services: + +- **Rivet Engine**: Main orchestration service +- **Rivet Shell**: Interactive shell for debugging +- **Runner**: Executes user code +- **ClickHouse**: Analytics and time-series database +- **PostgreSQL**: Relational database +- **Vector Server**: Log aggregation and processing +- **OpenTelemetry Collector**: Observability data collection + +## Port Configuration + +| Service | Port(s) | Description | +|---------|---------|-------------| +| Rivet Engine | ${ports.rivetEngineGuard} | Public endpoint | +| Runner | ${ports.runner} | Code execution service | +| PostgreSQL | ${ports.postgres} | Database | +| ClickHouse HTTP | ${ports.clickhouseHttp} | Database HTTP interface | +| ClickHouse Native | ${ports.clickhouseNative} | Database native protocol | +| OpenTelemetry gRPC | ${ports.otelGrpc} | OTLP gRPC endpoint | +| OpenTelemetry HTTP | ${ports.otelHttp} | OTLP HTTP endpoint | + +## Template Configuration + +**Template Name**: \`${templateName}\` +**Base Port**: \`6420\` +**Network Mode**: \`${config.networkMode}\` + +### Datacenters +${config.datacenters.map((dc) => `- **${dc.id}**: ${dc.engines} engine(s), ${dc.runners} runner(s)`).join("\n")} + +## Usage + +1. Start all services: + \`\`\`bash + docker-compose up -d + \`\`\` + +2. Check service health: + \`\`\`bash + docker-compose ps + \`\`\` + +3. View logs: + \`\`\`bash + docker-compose logs -f [service-name] + \`\`\` + +4. Stop all services: + \`\`\`bash + docker-compose down + \`\`\` + +## Generated Files + +This template generates the following files and directories: +- \`docker-compose.yml\` - Main Docker Compose configuration +- \`core/\` - Core services shared across datacenters: + - \`clickhouse/\` - ClickHouse configuration and initialization + - \`vector-server/\` - Vector aggregator configuration + - \`otel-collector-server/\` - OpenTelemetry Collector server configuration +- \`datacenters/\` - Datacenter-specific configurations: +${config.datacenters + .map( + (dc) => ` - \`${dc.id}/\` - Configuration for datacenter ${dc.id}: + - \`postgres/\` - PostgreSQL setup scripts + - \`rivet-engine/\` - Rivet Engine configuration + - \`vector-client/\` - Vector client configuration + - \`otel-collector-client/\` - OpenTelemetry Collector client configuration`, + ) + .join("\n")} +- \`README.md\` - This file +`; + + context.writeFile("README.md", readmeContent); +} diff --git a/docker/template/src/services/core/clickhouse.ts b/docker/template/src/services/core/clickhouse.ts new file mode 100644 index 0000000000..f4da3c3b0d --- /dev/null +++ b/docker/template/src/services/core/clickhouse.ts @@ -0,0 +1,215 @@ +import { TemplateContext } from "../../context"; + +export function generateCoreClickhouse(context: TemplateContext) { + // ClickHouse configuration + const configXml = ` + + + debug + /var/log/clickhouse-server/clickhouse-server.log + /var/log/clickhouse-server/clickhouse-server.err.log + 1000M + 10 + + + :: + 9300 + 9301 + + + 9440 + 9010 + + 9009 + + 4096 + 3 + 100 + 8589934592 + 5368709120 + + /var/lib/clickhouse/ + /var/lib/clickhouse/tmp/ + /var/lib/clickhouse/user_files/ + /var/lib/clickhouse/access/ + + users.xml + default + default + UTC + + + + + + 3600 + 3600 + 60 + + + system + query_log
+ 7500 +
+ + *_dictionary.xml +
+`; + + const usersXml = ` + + + + default + + ::/0 + + default + default + 1 + + + + + + 10000000000 + 0 + random + + + + + + + 3600 + 0 + 0 + 0 + 0 + 0 + + + + +`; + + const clientConfigXml = ` + + 9301 + 127.0.0.1 +`; + + const initSql = `CREATE DATABASE IF NOT EXISTS otel; + +CREATE TABLE IF NOT EXISTS otel.otel_logs ( + Timestamp DateTime64(9) CODEC(Delta, ZSTD(1)), + ObservedTimestamp DateTime64(9) CODEC(Delta, ZSTD(1)), + TraceId String CODEC(ZSTD(1)), + SpanId String CODEC(ZSTD(1)), + TraceFlags UInt32 CODEC(ZSTD(1)), + SeverityText LowCardinality(String) CODEC(ZSTD(1)), + SeverityNumber Int32 CODEC(ZSTD(1)), + ServiceName LowCardinality(String) CODEC(ZSTD(1)), + Body String CODEC(ZSTD(1)), + ResourceSchemaUrl String CODEC(ZSTD(1)), + ResourceAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ScopeSchemaUrl String CODEC(ZSTD(1)), + ScopeName String CODEC(ZSTD(1)), + ScopeVersion String CODEC(ZSTD(1)), + ScopeAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + LogAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + INDEX idx_trace_id TraceId TYPE bloom_filter(0.001) GRANULARITY 1, + INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_key mapKeys(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_value mapValues(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_log_attr_key mapKeys(LogAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_log_attr_value mapValues(LogAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_body Body TYPE tokenbf_v1(32768, 3, 0) GRANULARITY 1 +) ENGINE = MergeTree() +PARTITION BY toDate(Timestamp) +ORDER BY (ServiceName, SeverityText, toUnixTimestamp(Timestamp), TraceId) +TTL toDateTime(Timestamp) + toIntervalDay(3) +SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1; + +CREATE TABLE IF NOT EXISTS otel.otel_traces ( + Timestamp DateTime64(9) CODEC(Delta, ZSTD(1)), + TraceId String CODEC(ZSTD(1)), + SpanId String CODEC(ZSTD(1)), + ParentSpanId String CODEC(ZSTD(1)), + TraceState String CODEC(ZSTD(1)), + SpanName LowCardinality(String) CODEC(ZSTD(1)), + SpanKind LowCardinality(String) CODEC(ZSTD(1)), + ServiceName LowCardinality(String) CODEC(ZSTD(1)), + ResourceAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ScopeName String CODEC(ZSTD(1)), + ScopeVersion String CODEC(ZSTD(1)), + SpanAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + Duration Int64 CODEC(ZSTD(1)), + StatusCode LowCardinality(String) CODEC(ZSTD(1)), + StatusMessage String CODEC(ZSTD(1)), + Events Nested ( + Timestamp DateTime64(9), + Name LowCardinality(String), + Attributes Map(LowCardinality(String), String) + ) CODEC(ZSTD(1)), + Links Nested ( + TraceId String, + SpanId String, + TraceState String, + Attributes Map(LowCardinality(String), String) + ) CODEC(ZSTD(1)), + INDEX idx_trace_id TraceId TYPE bloom_filter(0.001) GRANULARITY 1, + INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_span_attr_key mapKeys(SpanAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_span_attr_value mapValues(SpanAttributes) TYPE bloom_filter(0.01) GRANULARITY 1 +) ENGINE = MergeTree() +PARTITION BY toDate(Timestamp) +ORDER BY (ServiceName, SpanName, toUnixTimestamp(Timestamp), TraceId) +TTL toDateTime(Timestamp) + toIntervalDay(7) +SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1; + +CREATE TABLE IF NOT EXISTS otel.otel_metrics ( + ResourceAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ResourceSchemaUrl String CODEC(ZSTD(1)), + ScopeName String CODEC(ZSTD(1)), + ScopeVersion String CODEC(ZSTD(1)), + ScopeAttributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + ScopeDroppedAttrCount UInt32 CODEC(ZSTD(1)), + ScopeSchemaUrl String CODEC(ZSTD(1)), + MetricName String CODEC(ZSTD(1)), + MetricDescription String CODEC(ZSTD(1)), + MetricUnit String CODEC(ZSTD(1)), + Attributes Map(LowCardinality(String), String) CODEC(ZSTD(1)), + StartTimeUnix DateTime64(9) CODEC(Delta, ZSTD(1)), + TimeUnix DateTime64(9) CODEC(Delta, ZSTD(1)), + Value Float64 CODEC(ZSTD(1)), + Flags UInt32 CODEC(ZSTD(1)), + Exemplars Nested ( + FilteredAttributes Map(LowCardinality(String), String), + TimeUnix DateTime64(9), + Value Float64, + SpanId String, + TraceId String + ) CODEC(ZSTD(1)), + AggTemp Int32 CODEC(ZSTD(1)), + IsMonotonic Bool CODEC(ZSTD(1)), + INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_key mapKeys(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_scope_attr_value mapValues(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_attr_key mapKeys(Attributes) TYPE bloom_filter(0.01) GRANULARITY 1, + INDEX idx_attr_value mapValues(Attributes) TYPE bloom_filter(0.01) GRANULARITY 1 +) ENGINE = MergeTree() +PARTITION BY toDate(TimeUnix) +ORDER BY (MetricName, Attributes, toUnixTimestamp(TimeUnix)) +TTL toDateTime(TimeUnix) + toIntervalDay(30) +SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1; +`; + + context.writeCoreServiceFile("clickhouse", "config.xml", configXml); + context.writeCoreServiceFile("clickhouse", "users.xml", usersXml); + context.writeCoreServiceFile("clickhouse", "client-config.xml", clientConfigXml); + context.writeCoreServiceFile("clickhouse", "init/01-create-otel-table.sql", initSql); +} \ No newline at end of file diff --git a/docker/template/src/services/core/grafana.ts b/docker/template/src/services/core/grafana.ts new file mode 100644 index 0000000000..607cb7bff3 --- /dev/null +++ b/docker/template/src/services/core/grafana.ts @@ -0,0 +1,99 @@ +import { TemplateContext } from "../../context"; +import * as fs from "fs"; +import * as path from "path"; +import * as yaml from "js-yaml"; + +export function generateCoreGrafana(context: TemplateContext) { + const clickhouseHost = context.config.networkMode === "host" ? "127.0.0.1" : "clickhouse"; + // Grafana configuration + const grafanaIni = `[server] +http_port = 3000 +root_url = http://localhost:3100 + +[security] +admin_user = admin +admin_password = admin + +[auth.anonymous] +enabled = true +org_role = Viewer + +[dashboards] +default_home_dashboard_path = /var/lib/grafana/dashboards/api.json +`; + + // Datasource configuration for ClickHouse + const datasourcesConfig = { + apiVersion: 1, + datasources: [ + { + name: "ClickHouse", + uid: "clickhouse", + type: "grafana-clickhouse-datasource", + access: "proxy", + secureJsonData: { + password: "default" + }, + jsonData: { + version: "2.0.0", + host: clickhouseHost, + port: 9300, + defaultDatabase: "default", + protocol: "http", + secure: false, + username: "default", + validateSql: true, + logs: { + otelEnabled: true, + otelVersion: "1.2.9", + defaultDatabase: "otel", + defaultTable: "otel_logs", + timeColumn: "TimestampTime", + messageColumn: "Body", + levelColumn: "SeverityText" + }, + traces: { + otelEnabled: true, + otelVersion: "1.2.9", + defaultDatabase: "otel", + defaultTable: "otel_traces" + } + } + } + ] + }; + + // Dashboard provisioning configuration + const dashboardsConfig = { + apiVersion: 1, + providers: [ + { + name: "rivet-dashboards", + orgId: 1, + folder: "", + type: "file", + disableDeletion: false, + updateIntervalSeconds: 10, + options: { + path: "/var/lib/grafana/dashboards" + } + } + ] + }; + + // Write configuration files + context.writeCoreServiceFile("grafana", "grafana.ini", grafanaIni); + context.writeCoreServiceFile("grafana", "provisioning/datasources/datasources.yaml", yaml.dump(datasourcesConfig)); + context.writeCoreServiceFile("grafana", "provisioning/dashboards/dashboards.yaml", yaml.dump(dashboardsConfig)); + + // Copy all dashboard files from the template directory + const dashboardsDir = path.join(__dirname, "../../../grafana-dashboards"); + const dashboardFiles = fs.readdirSync(dashboardsDir); + + dashboardFiles.forEach(file => { + if (file.endsWith('.json')) { + const dashboardContent = fs.readFileSync(path.join(dashboardsDir, file), "utf-8"); + context.writeCoreServiceFile("grafana", `dashboards/${file}`, dashboardContent); + } + }); +} diff --git a/docker/template/src/services/edge/otel-collector-client.ts b/docker/template/src/services/edge/otel-collector-client.ts new file mode 100644 index 0000000000..eadcca3e6b --- /dev/null +++ b/docker/template/src/services/edge/otel-collector-client.ts @@ -0,0 +1,64 @@ +import { TemplateContext } from "../../context"; +import * as yaml from "js-yaml"; + +export function generateDatacenterOtelCollectorClient( + context: TemplateContext, + dcId: string, +) { + const otelConfig = { + receivers: { + otlp: { + protocols: { + grpc: { + endpoint: "0.0.0.0:4317", + }, + http: { + endpoint: "0.0.0.0:4318", + }, + }, + }, + }, + processors: { + batch: { + timeout: "5s", + send_batch_size: 10000, + }, + }, + exporters: { + "otlp/server": { + endpoint: `${context.getServiceHost("otel-collector-server", dcId)}:4317`, + tls: { + insecure: true, + }, + }, + }, + service: { + pipelines: { + logs: { + receivers: ["otlp"], + processors: ["batch"], + exporters: ["otlp/server"], + }, + traces: { + receivers: ["otlp"], + processors: ["batch"], + exporters: ["otlp/server"], + }, + metrics: { + receivers: ["otlp"], + processors: ["batch"], + exporters: ["otlp/server"], + }, + }, + }, + }; + + const yamlContent = yaml.dump(otelConfig); + + context.writeDatacenterServiceFile( + "otel-collector-client", + dcId, + "config.yaml", + yamlContent, + ); +} diff --git a/docker/template/src/services/edge/otel-collector-server.ts b/docker/template/src/services/edge/otel-collector-server.ts new file mode 100644 index 0000000000..9ff9e0b6b5 --- /dev/null +++ b/docker/template/src/services/edge/otel-collector-server.ts @@ -0,0 +1,84 @@ +import { TemplateContext } from "../../context"; +import * as yaml from "js-yaml"; + +export function generateDatacenterOtelCollectorServer(context: TemplateContext, dcId: string) { + const clickhouseHost = context.config.networkMode === "host" ? "127.0.0.1" : "clickhouse"; + const otelConfig = { + receivers: { + otlp: { + protocols: { + grpc: { + endpoint: "0.0.0.0:4317" + }, + } + }, + }, + processors: { + batch: { + timeout: "5s", + send_batch_size: 10000 + } + }, + exporters: { + clickhouse: { + endpoint: `http://${clickhouseHost}:9300`, + database: "otel", + username: "default", + password: "${env:CLICKHOUSE_PASSWORD}", + async_insert: true, + ttl: "72h", + compress: "lz4", + create_schema: true, + logs_table_name: "otel_logs", + traces_table_name: "otel_traces", + timeout: "5s", + metrics_tables: { + gauge: { + name: "otel_metrics_gauge" + }, + sum: { + name: "otel_metrics_sum" + }, + summary: { + name: "otel_metrics_summary" + }, + histogram: { + name: "otel_metrics_histogram" + }, + exponential_histogram: { + name: "otel_metrics_exp_histogram" + } + }, + retry_on_failure: { + enabled: true, + initial_interval: "5s", + max_interval: "30s", + max_elapsed_time: "300s" + } + } + }, + service: { + pipelines: { + logs: { + receivers: ["otlp"], + processors: ["batch"], + exporters: ["clickhouse"] + }, + traces: { + receivers: ["otlp"], + processors: ["batch"], + exporters: ["clickhouse"] + }, + metrics: { + receivers: ["otlp"], + processors: ["batch"], + exporters: ["clickhouse"] + } + } + } + }; + + const yamlContent = yaml.dump(otelConfig); + + context.writeDatacenterServiceFile("otel-collector-server", dcId, "config.yaml", yamlContent); +} diff --git a/docker/template/src/services/edge/postgres.ts b/docker/template/src/services/edge/postgres.ts new file mode 100644 index 0000000000..69cf16993a --- /dev/null +++ b/docker/template/src/services/edge/postgres.ts @@ -0,0 +1,23 @@ +import { TemplateContext } from "../../context"; + +export function generateDatacenterPostgres( + context: TemplateContext, + dcId: string, +) { + // Generate a basic PostgreSQL initialization script + const initScript = `#!/bin/bash +set -e + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + CREATE DATABASE rivet_engine; +EOSQL +`; + + context.writeDatacenterServiceFile( + "postgres", + dcId, + "init-db.sh", + initScript, + ); + context.makeDatabaseFileExec("postgres", dcId, "init-db.sh"); +} \ No newline at end of file diff --git a/docker/template/src/services/edge/rivet-engine.ts b/docker/template/src/services/edge/rivet-engine.ts new file mode 100644 index 0000000000..c730d428e7 --- /dev/null +++ b/docker/template/src/services/edge/rivet-engine.ts @@ -0,0 +1,102 @@ +import { TemplateContext } from "../../context"; +import { Datacenter } from "../../config"; + +const API_PEER_PORT = 6422; +const GUARD_PORT = 6420; + +export function generateDatacenterRivetEngine( + context: TemplateContext, + datacenter: Datacenter, +) { + const clickhouseHost = context.config.networkMode === "host" ? "127.0.0.1" : "clickhouse"; + const datacenters = []; + + for (let dc of context.config.datacenters) { + let serviceHost = context.getServiceHost("rivet-engine", dc.name, 0); + datacenters.push({ + name: dc.name, + datacenter_label: dc.id, + is_leader: dc.id == 1, + api_peer_url: `http://${serviceHost}:${API_PEER_PORT}`, + guard_url: `http://${serviceHost}:${GUARD_PORT}`, + }); + } + + // Generate a separate config file for each engine node + for (let i = 0; i < datacenter.engines; i++) { + let serviceHost = context.getServiceHost("rivet-engine", datacenter.name, 0); + const topology = { + datacenter_label: datacenter.id, + datacenters, + }; + + // Config structure matching Rust schema in packages/common/config/src/config/mod.rs + const config = { + // guard config + guard: { + port: GUARD_PORT, + // https is optional and not configured for local development + }, + // api_public config + api_public: { + lan_host: serviceHost, + host: "0.0.0.0", + port: 6421, + }, + // api_peer config + api_peer: { + host: "0.0.0.0", + port: API_PEER_PORT, + }, + // pegboard config + pegboard: { + lan_host: serviceHost, + host: "0.0.0.0", + port: 6423, + }, + // logs config + logs: { + // redirect_logs_dir is optional + }, + // topology config + topology, + // database & pubsub config + postgres: { + url: `postgresql://postgres:postgres@${context.getServiceHost("postgres", datacenter.name)}:5432/rivet_engine`, + }, + // cache config + cache: { + driver: "in_memory", + }, + // clickhouse config (optional) + clickhouse: { + http_url: `http://${clickhouseHost}:9300`, // TODO: + native_url: `http://${clickhouseHost}:9301`, // TODO: + username: "system", + password: "default", + // TODO: Move this to init migrations + provision_users: { + vector: { + username: "vector", + password: "vector", + role: "write", + }, + }, + secure: false, + }, + // vector_http config (optional) + vector_http: { + host: context.getServiceHost("vector-client", datacenter.name), + port: 5022, + }, + }; + + context.writeDatacenterServiceFile( + "rivet-engine", + datacenter.name, + "config.jsonc", + JSON.stringify(config, null, "\t"), + i, + ); + } +} diff --git a/docker/template/src/services/edge/runner.ts b/docker/template/src/services/edge/runner.ts new file mode 100644 index 0000000000..091399e707 --- /dev/null +++ b/docker/template/src/services/edge/runner.ts @@ -0,0 +1,7 @@ +import { TemplateContext } from '../../context'; + +export function generateRunner(context: TemplateContext) { + // The runner files are shared and located at sdks/typescript/test-runner/ + // We just need to reference them in the docker-compose + // No specific files need to be generated here for now +} diff --git a/docker/template/src/services/edge/vector-client.ts b/docker/template/src/services/edge/vector-client.ts new file mode 100644 index 0000000000..60a88cff4b --- /dev/null +++ b/docker/template/src/services/edge/vector-client.ts @@ -0,0 +1,49 @@ +import { TemplateContext } from "../../context"; +import * as yaml from "js-yaml"; + +export function generateDatacenterVectorClient(context: TemplateContext, dcId: string) { + const vectorConfig = { + api: { + enabled: true, + address: "0.0.0.0:8686" + }, + sources: { + http_events: { + type: "http_server", + address: "0.0.0.0:5022", + encoding: "ndjson" + }, + }, + transforms: {}, + sinks: { + vector_server: { + type: "vector", + inputs: [ + "http_events" + ], + address: `${context.getServiceHost("vector-server", dcId)}:6000`, + version: "2", + buffer: { + type: "disk", + max_size: 2147483648, + when_full: "block" + } + }, + console_debug: { + type: "console", + inputs: ["http_events"], + encoding: { + codec: "json" + }, + } + } + }; + + const yamlContent = `# Vector Client Configuration for Datacenter: ${dcId} +# This Vector instance runs on each server to collect local logs and forward them +# to the central Vector server aggregator. + +${yaml.dump(vectorConfig)} `; + + context.writeDatacenterServiceFile("vector-client", dcId, "vector.yaml", yamlContent); +} diff --git a/docker/template/src/services/edge/vector-server.ts b/docker/template/src/services/edge/vector-server.ts new file mode 100644 index 0000000000..4c33e3d8c8 --- /dev/null +++ b/docker/template/src/services/edge/vector-server.ts @@ -0,0 +1,106 @@ +import { TemplateContext } from "../../context"; +import * as yaml from "js-yaml"; + +export function generateDatacenterVectorServer(context: TemplateContext, dcId: string) { + const clickhouseHost = context.config.networkMode === "host" ? "127.0.0.1" : "clickhouse"; + const vectorConfig = { + api: { + enabled: true, + address: "0.0.0.0:8686" + }, + sources: { + vector: { + type: "vector", + address: "0.0.0.0:6000", + version: "2" + }, + tcp_json: { + type: "socket", + mode: "tcp", + address: "0.0.0.0:6100", + decoding: { + codec: "json" + } + }, + http_json: { + type: "http_server", + address: "0.0.0.0:6200", + encoding: "json" + }, + vector_metrics: { + type: "internal_metrics" + }, + vector_logs: { + type: "internal_logs" + } + }, + transforms: { + clickhouse_dynamic_events_filter: { + type: "filter", + inputs: [ + "vector" + ], + condition: { + type: "vrl", + source: `.source == "clickhouse"` + } + }, + clickhouse_dynamic_events_transform: { + type: "remap", + inputs: [ + "clickhouse_dynamic_events_filter" + ], + source: `# Extract and store metadata +__database = .database +__table = .table +__columns = .columns + +# Create a new object with just the columns data +. = { + "__database": __database, + "__table": __table, + # By default insert namespace column since most tables include this + "namespace": "rivet" +} + +# Merge in the column data that should be inserted +. = merge!(., __columns) +` + } + }, + sinks: { + clickhouse_dynamic_events: { + type: "clickhouse", + inputs: ["clickhouse_dynamic_events_transform"], + endpoint: `http://${clickhouseHost}:9300`, + database: "{{ __database }}", + table: "{{ __table }}", + compression: "gzip", + auth: { + strategy: "basic", + user: "system", + password: "default" + }, + batch: { + max_events: 1000, + timeout_secs: 10 + } + }, + console_vector_logs: { + type: "console", + inputs: ["vector_logs"], + encoding: { + codec: "json" + } + } + } + }; + + const yamlContent = `# Vector Server (Aggregator) Configuration +# This Vector instance acts as an aggregator that collects logs and metrics from all Vector clients +# across different datacenters and forwards them to ClickHouse and other sinks. + +${yaml.dump(vectorConfig)}`; + + context.writeDatacenterServiceFile("vector-server", dcId, "vector.yaml", yamlContent); +} diff --git a/docker/template/src/utils.ts b/docker/template/src/utils.ts new file mode 100644 index 0000000000..be5814bbd1 --- /dev/null +++ b/docker/template/src/utils.ts @@ -0,0 +1,19 @@ +import * as fs from "node:fs"; +import * as path from "node:path"; + +// Utility function to read fixture files +export function readFixture(fixturePath: string): string { + const fullPath = path.join(__dirname, "../fixtures", fixturePath); + return fs.readFileSync(fullPath, "utf8"); +} + +export function ensureDir(dirPath: string) { + if (!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath, { recursive: true }); + } +} + +export function writeFile(filePath: string, content: string) { + ensureDir(path.dirname(filePath)); + fs.writeFileSync(filePath, content); +} diff --git a/docker/template/tsconfig.json b/docker/template/tsconfig.json new file mode 100644 index 0000000000..a1e561e417 --- /dev/null +++ b/docker/template/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022"], + "module": "CommonJS", + "moduleResolution": "node", + "outDir": "./dist", + "rootDir": "./src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "types": ["node"] + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/docker/toolchain/linux-aarch64.Dockerfile b/docker/toolchain/linux-aarch64.Dockerfile deleted file mode 100644 index ee3af327aa..0000000000 --- a/docker/toolchain/linux-aarch64.Dockerfile +++ /dev/null @@ -1,58 +0,0 @@ -# syntax=docker/dockerfile:1.4 -FROM rust:1.82.0 AS base - -# Install dependencies -RUN apt-get update && apt-get install -y \ - musl-tools \ - libssl-dev \ - pkg-config \ - protobuf-compiler \ - ca-certificates \ - git-lfs \ - musl-dev \ - && rm -rf /var/lib/apt/lists/* - -# Install musl targets -RUN rustup target add aarch64-unknown-linux-musl - -# Set environment variables -ENV CARGO_INCREMENTAL=0 \ - RUSTFLAGS="--cfg tokio_unstable" \ - CARGO_NET_GIT_FETCH_WITH_CLI=true - -# Set working directory -WORKDIR /build - -# Build for aarch64 -FROM base AS aarch64-builder - -# Set up OpenSSL for aarch64 musl target -ENV SSL_VER=1.1.1w -RUN wget https://www.openssl.org/source/openssl-$SSL_VER.tar.gz \ - && tar -xzf openssl-$SSL_VER.tar.gz \ - && cd openssl-$SSL_VER \ - && ./Configure no-shared no-async --prefix=/musl-aarch64 --openssldir=/musl-aarch64/ssl linux-aarch64 \ - && make -j$(nproc) \ - && make install_sw \ - && cd .. \ - && rm -rf openssl-$SSL_VER* - -# Configure OpenSSL env vars for the build -ENV OPENSSL_DIR=/musl-aarch64 \ - OPENSSL_INCLUDE_DIR=/musl-aarch64/include \ - OPENSSL_LIB_DIR=/musl-aarch64/lib \ - PKG_CONFIG_ALLOW_CROSS=1 - -# Copy the source code -COPY . . - -# Build for Linux with musl (static binary) - aarch64 -RUN --mount=type=cache,target=/usr/local/cargo/registry \ - --mount=type=cache,target=/usr/local/cargo/git \ - --mount=type=cache,target=/build/target \ - cargo build --bin rivet --release --target aarch64-unknown-linux-musl -v && \ - mkdir -p /artifacts && \ - cp target/aarch64-unknown-linux-musl/release/rivet /artifacts/rivet-aarch64-unknown-linux-musl - -# Default command to show help -CMD ["ls", "-la", "/artifacts"] \ No newline at end of file diff --git a/docker/toolchain/linux-x86_64.Dockerfile b/docker/toolchain/linux-x86_64.Dockerfile deleted file mode 100644 index cabae7299f..0000000000 --- a/docker/toolchain/linux-x86_64.Dockerfile +++ /dev/null @@ -1,58 +0,0 @@ -# syntax=docker/dockerfile:1.4 -FROM rust:1.82.0 AS base - -# Install dependencies -RUN apt-get update && apt-get install -y \ - musl-tools \ - libssl-dev \ - pkg-config \ - protobuf-compiler \ - ca-certificates \ - git-lfs \ - musl-dev \ - && rm -rf /var/lib/apt/lists/* - -# Install musl targets -RUN rustup target add x86_64-unknown-linux-musl - -# Set environment variables -ENV CARGO_INCREMENTAL=0 \ - RUSTFLAGS="--cfg tokio_unstable" \ - CARGO_NET_GIT_FETCH_WITH_CLI=true - -# Set working directory -WORKDIR /build - -# Build for x86_64 -FROM base AS x86_64-builder - -# Set up OpenSSL for x86_64 musl target -ENV SSL_VER=1.1.1w -RUN wget https://www.openssl.org/source/openssl-$SSL_VER.tar.gz \ - && tar -xzf openssl-$SSL_VER.tar.gz \ - && cd openssl-$SSL_VER \ - && ./Configure no-shared no-async --prefix=/musl --openssldir=/musl/ssl linux-x86_64 \ - && make -j$(nproc) \ - && make install_sw \ - && cd .. \ - && rm -rf openssl-$SSL_VER* - -# Configure OpenSSL env vars for the build -ENV OPENSSL_DIR=/musl \ - OPENSSL_INCLUDE_DIR=/musl/include \ - OPENSSL_LIB_DIR=/musl/lib \ - PKG_CONFIG_ALLOW_CROSS=1 - -# Copy the source code -COPY . . - -# Build for Linux with musl (static binary) - x86_64 -RUN --mount=type=cache,target=/usr/local/cargo/registry \ - --mount=type=cache,target=/usr/local/cargo/git \ - --mount=type=cache,target=/build/target \ - cargo build --bin rivet --release --target x86_64-unknown-linux-musl -v && \ - mkdir -p /artifacts && \ - cp target/x86_64-unknown-linux-musl/release/rivet /artifacts/rivet-x86_64-unknown-linux-musl - -# Default command to show help -CMD ["ls", "-la", "/artifacts"] \ No newline at end of file diff --git a/docker/toolchain/macos-aarch64.Dockerfile b/docker/toolchain/macos-aarch64.Dockerfile deleted file mode 100644 index 956b369d49..0000000000 --- a/docker/toolchain/macos-aarch64.Dockerfile +++ /dev/null @@ -1,71 +0,0 @@ -# syntax=docker/dockerfile:1.4 -FROM rust:1.82.0 AS base - -# Install dependencies -RUN apt-get update && apt-get install -y \ - git-lfs \ - protobuf-compiler \ - clang \ - cmake \ - patch \ - libxml2-dev \ - wget \ - xz-utils \ - curl \ - && rm -rf /var/lib/apt/lists/* - -# Install osxcross -RUN git config --global --add safe.directory '*' && \ - git clone https://github.com/tpoechtrager/osxcross /root/osxcross && \ - cd /root/osxcross && \ - wget -nc https://github.com/phracker/MacOSX-SDKs/releases/download/11.3/MacOSX11.3.sdk.tar.xz && \ - mv MacOSX11.3.sdk.tar.xz tarballs/ && \ - UNATTENDED=yes OSX_VERSION_MIN=10.7 ./build.sh - -# Add osxcross to PATH -ENV PATH="/root/osxcross/target/bin:$PATH" - -# Common environment variables for cross-compilation -ENV MACOSX_DEPLOYMENT_TARGET=10.7 \ - # Skip aws-lc-rs with rustls certs config when building for macOS - RUSTFLAGS="--cfg tokio_unstable --cfg rustls_native_certs --cfg aws_lc_rs" \ - CARGO_FEATURE_RUSTLS_NATIVE_CERTS=0 \ - CARGO_RUSTLS_NATIVE_CERTS=0 \ - CARGO_INCREMENTAL=0 \ - CARGO_NET_GIT_FETCH_WITH_CLI=true - -# Set working directory -WORKDIR /build - -# Build for ARM64 macOS -FROM base AS aarch64-builder - -# Install macOS ARM64 target -RUN rustup target add aarch64-apple-darwin - -# Configure Cargo for cross-compilation (ARM64) -RUN mkdir -p /root/.cargo && \ - echo '\ -[target.aarch64-apple-darwin]\n\ -linker = "aarch64-apple-darwin20.4-clang"\n\ -ar = "aarch64-apple-darwin20.4-ar"\n\ -' > /root/.cargo/config.toml - -# Set environment variables for ARM64 cross-compilation -ENV CARGO_TARGET_AARCH64_APPLE_DARWIN_LINKER=aarch64-apple-darwin20.4-clang \ - CC_aarch64_apple_darwin=aarch64-apple-darwin20.4-clang \ - CXX_aarch64_apple_darwin=aarch64-apple-darwin20.4-clang++ - -# Copy the source code -COPY . . - -# Build for ARM64 macOS -RUN --mount=type=cache,target=/usr/local/cargo/registry \ - --mount=type=cache,target=/usr/local/cargo/git \ - --mount=type=cache,target=/build/target \ - cargo build --bin rivet --release --target aarch64-apple-darwin && \ - mkdir -p /artifacts && \ - cp target/aarch64-apple-darwin/release/rivet /artifacts/rivet-aarch64-apple-darwin - -# Default command to show help -CMD ["ls", "-la", "/artifacts"] \ No newline at end of file diff --git a/docker/toolchain/macos-x86_64.Dockerfile b/docker/toolchain/macos-x86_64.Dockerfile deleted file mode 100644 index 3fd3c25368..0000000000 --- a/docker/toolchain/macos-x86_64.Dockerfile +++ /dev/null @@ -1,71 +0,0 @@ -# syntax=docker/dockerfile:1.4 -FROM rust:1.82.0 AS base - -# Install dependencies -RUN apt-get update && apt-get install -y \ - git-lfs \ - protobuf-compiler \ - clang \ - cmake \ - patch \ - libxml2-dev \ - wget \ - xz-utils \ - curl \ - && rm -rf /var/lib/apt/lists/* - -# Install osxcross -RUN git config --global --add safe.directory '*' && \ - git clone https://github.com/tpoechtrager/osxcross /root/osxcross && \ - cd /root/osxcross && \ - wget -nc https://github.com/phracker/MacOSX-SDKs/releases/download/11.3/MacOSX11.3.sdk.tar.xz && \ - mv MacOSX11.3.sdk.tar.xz tarballs/ && \ - UNATTENDED=yes OSX_VERSION_MIN=10.7 ./build.sh - -# Add osxcross to PATH -ENV PATH="/root/osxcross/target/bin:$PATH" - -# Common environment variables for cross-compilation -ENV MACOSX_DEPLOYMENT_TARGET=10.7 \ - # Skip aws-lc-rs with rustls certs config when building for macOS - RUSTFLAGS="--cfg tokio_unstable --cfg rustls_native_certs --cfg aws_lc_rs" \ - CARGO_FEATURE_RUSTLS_NATIVE_CERTS=0 \ - CARGO_RUSTLS_NATIVE_CERTS=0 \ - CARGO_INCREMENTAL=0 \ - CARGO_NET_GIT_FETCH_WITH_CLI=true - -# Set working directory -WORKDIR /build - -# Build for x86_64 macOS -FROM base AS x86_64-builder - -# Install macOS x86_64 target -RUN rustup target add x86_64-apple-darwin - -# Configure Cargo for cross-compilation (x86_64) -RUN mkdir -p /root/.cargo && \ - echo '\ -[target.x86_64-apple-darwin]\n\ -linker = "x86_64-apple-darwin20.4-clang"\n\ -ar = "x86_64-apple-darwin20.4-ar"\n\ -' > /root/.cargo/config.toml - -# Set environment variables for x86_64 cross-compilation -ENV CARGO_TARGET_X86_64_APPLE_DARWIN_LINKER=x86_64-apple-darwin20.4-clang \ - CC_x86_64_apple_darwin=x86_64-apple-darwin20.4-clang \ - CXX_x86_64_apple_darwin=x86_64-apple-darwin20.4-clang++ - -# Copy the source code -COPY . . - -# Build for x86_64 macOS -RUN --mount=type=cache,target=/usr/local/cargo/registry \ - --mount=type=cache,target=/usr/local/cargo/git \ - --mount=type=cache,target=/build/target \ - cargo build --bin rivet --release --target x86_64-apple-darwin && \ - mkdir -p /artifacts && \ - cp target/x86_64-apple-darwin/release/rivet /artifacts/rivet-x86_64-apple-darwin - -# Default command to show help -CMD ["ls", "-la", "/artifacts"] \ No newline at end of file diff --git a/docker/toolchain/windows.Dockerfile b/docker/toolchain/windows.Dockerfile deleted file mode 100644 index 13b6c244e8..0000000000 --- a/docker/toolchain/windows.Dockerfile +++ /dev/null @@ -1,43 +0,0 @@ -# syntax=docker/dockerfile:1.4 -FROM rust:1.82.0 - -# Install dependencies -RUN apt-get update && apt-get install -y \ - git-lfs \ - protobuf-compiler \ - gcc-mingw-w64-x86-64 \ - ca-certificates \ - && rm -rf /var/lib/apt/lists/* - -# Install target -RUN rustup target add x86_64-pc-windows-gnu - -# Configure Cargo for Windows cross-compilation -RUN mkdir -p /root/.cargo && \ - echo '\ -[target.x86_64-pc-windows-gnu]\n\ -linker = "x86_64-w64-mingw32-gcc"\n\ -' > /root/.cargo/config.toml - -# Set environment variables for cross-compilation -ENV CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=x86_64-w64-mingw32-gcc \ - RUSTFLAGS="--cfg tokio_unstable" \ - CARGO_INCREMENTAL=0 \ - CARGO_NET_GIT_FETCH_WITH_CLI=true - -# Set working directory -WORKDIR /build - -# Copy the source code -COPY . . - -# Build for Windows -RUN --mount=type=cache,target=/usr/local/cargo/registry \ - --mount=type=cache,target=/usr/local/cargo/git \ - --mount=type=cache,target=/build/target \ - cargo build --bin rivet --release --target x86_64-pc-windows-gnu && \ - mkdir -p /artifacts && \ - cp target/x86_64-pc-windows-gnu/release/rivet.exe /artifacts/rivet-x86_64-pc-windows-gnu.exe - -# Default command to show help -CMD ["ls", "-la", "/artifacts"] diff --git a/docker/universal/Dockerfile b/docker/universal/Dockerfile index 7e542bf207..990952bc72 100644 --- a/docker/universal/Dockerfile +++ b/docker/universal/Dockerfile @@ -2,7 +2,12 @@ # MARK: Builder # TODO(RVT-4168): Compile libfdb from scratch for ARM -FROM --platform=linux/amd64 rust:1.85.0-bookworm AS builder +FROM --platform=linux/amd64 rust:1.88.0-bookworm AS builder + +# Docker automatically provides TARGETARCH +ARG TARGETARCH + +ARG BUILD_FRONTEND=false ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update -y && \ @@ -18,15 +23,23 @@ RUN apt-get update -y && \ ca-certificates \ gpg \ openssl \ - wget && \ + wget \ + cmake \ + make && \ curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \ apt-get install -y nodejs && \ corepack enable && \ - curl -Lf -o /lib/libfdb_c.so "https://github.com/apple/foundationdb/releases/download/7.1.60/libfdb_c.x86_64.so" + if [ "$TARGETARCH" = "arm64" ]; then \ + curl -Lf -o /lib/libfdb_c.so "https://github.com/apple/foundationdb/releases/download/7.3.68/libfdb_c.aarch64.so"; \ + else \ + curl -Lf -o /lib/libfdb_c.so "https://github.com/apple/foundationdb/releases/download/7.3.68/libfdb_c.x86_64.so"; \ + fi # Disable interactive prompt ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0 +ENV RIVET_SKIP_BUILD_TS_SDK=1 + # Pull via Git CLI to improve reliability in CI ENV CARGO_NET_GIT_FETCH_WITH_CLI=true @@ -34,26 +47,30 @@ WORKDIR /app COPY . . +# Build frontend +RUN if [ "$BUILD_FRONTEND" = "true" ]; then \ + (cd sdks/typescript/api-full && pnpm install && pnpm run build) && \ + (cd frontend && pnpm install && pnpm run build); \ + fi + # Build and copy all binaries from target directory into an empty image (it is not # included in the output because of cache mount) RUN \ --mount=type=secret,id=netrc,target=/root/.netrc,mode=0600 \ - --mount=type=secret,id=fontawesome_package_token,env=FONTAWESOME_PACKAGE_TOKEN \ --mount=type=cache,target=/usr/local/cargo/git,id=univseral-cargo-git \ --mount=type=cache,target=/usr/local/cargo/registry,id=univseral-cargo-registry \ --mount=type=cache,target=/app/target,id=univseral-target \ - --mount=type=cache,target=/app/node_modules,id=universal-node-modules \ - --mount=type=cache,target=/app/.turbo,id=universal-turbo \ --mount=type=cache,target=/root/.cache,id=universal-user-cache \ - --mount=type=cache,target=/root/.npm,id=universal-user-npm \ - --mount=type=cache,target=/root/.yarn,id=universal-user-yarn \ - RUSTFLAGS="--cfg tokio_unstable" RIVET_BUILD_HUB=0 cargo build --bin rivet-server --bin rivet-edge-server --bin rivet-guard --bin rivet-client --bin rivet-isolate-v8-runner --bin rivet-container-runner && \ + RUSTFLAGS="--cfg tokio_unstable" cargo build --bin rivet-engine && \ # cargo install --locked tokio-console && \ mkdir /app/dist/ && \ - cp target/debug/rivet-server target/debug/rivet-edge-server target/debug/rivet-guard target/debug/rivet-client target/debug/rivet-isolate-v8-runner target/debug/rivet-container-runner /app/dist/ + cp target/debug/rivet-engine /app/dist/ + +# MARK: Engine (full, base) +FROM debian:12.9-slim AS engine-full-base -# MARK: Server (full, base) -FROM debian:12.9-slim AS server-full-base +# Docker automatically provides TARGETARCH +ARG TARGETARCH ENV DEBIAN_FRONTEND=noninteractive # - Install curl for health checks @@ -64,149 +81,52 @@ RUN apt-get update -y && \ ca-certificates \ openssl \ curl \ - redis-tools \ - postgresql-client \ + # redis-tools \ + # postgresql-client \ gpg \ dirmngr && \ - curl -fsSL 'https://packages.clickhouse.com/rpm/lts/repodata/repomd.xml.key' | gpg --dearmor -o /usr/share/keyrings/clickhouse-keyring.gpg && \ - echo "deb [signed-by=/usr/share/keyrings/clickhouse-keyring.gpg] https://packages.clickhouse.com/deb stable main" | tee /etc/apt/sources.list.d/clickhouse.list && \ - apt-get update -y && \ - apt-get install -y clickhouse-client && \ - (curl -L https://github.com/golang-migrate/migrate/releases/download/v4.18.1/migrate.linux-amd64.tar.gz | tar xvz) && \ - mv migrate /usr/local/bin/migrate && \ + # curl -fsSL 'https://packages.clickhouse.com/rpm/lts/repodata/repomd.xml.key' | gpg --dearmor -o /usr/share/keyrings/clickhouse-keyring.gpg && \ + # echo "deb [signed-by=/usr/share/keyrings/clickhouse-keyring.gpg] https://packages.clickhouse.com/deb stable main" | tee /etc/apt/sources.list.d/clickhouse.list && \ + # apt-get update -y && \ + # apt-get install -y clickhouse-client && \ + # (curl -L https://github.com/golang-migrate/migrate/releases/download/v4.18.1/migrate.linux-amd64.tar.gz | tar xvz) && \ + # mv migrate /usr/local/bin/migrate && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* && \ - curl -Lf -o /lib/libfdb_c.so "https://github.com/apple/foundationdb/releases/download/7.1.60/libfdb_c.x86_64.so" + if [ "$TARGETARCH" = "arm64" ]; then \ + curl -Lf -o /lib/libfdb_c.so "https://github.com/apple/foundationdb/releases/download/7.3.68/libfdb_c.aarch64.so"; \ + else \ + curl -Lf -o /lib/libfdb_c.so "https://github.com/apple/foundationdb/releases/download/7.3.68/libfdb_c.x86_64.so"; \ + fi -# MARK: Server (Full) -FROM server-full-base AS server-full +# MARK: Engine (Full) +FROM engine-full-base AS engine-full -COPY --from=builder /app/dist/rivet-server /usr/bin/rivet-server +LABEL org.opencontainers.image.source https://github.com/rivet-gg/rivet -CMD ["/usr/bin/rivet-server"] +COPY --from=builder /app/dist/rivet-engine /usr/bin/rivet-engine -# MARK: Server (Slim) -FROM debian:12.9-slim AS server-slim +CMD ["/usr/bin/rivet-engine", "start"] -ENV DEBIAN_FRONTEND=noninteractive -RUN apt-get update -y && \ - apt-get install -y ca-certificates openssl curl && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* && \ - curl -Lf -o /lib/libfdb_c.so "https://github.com/apple/foundationdb/releases/download/7.1.60/libfdb_c.x86_64.so" +# MARK: Engine (Slim) +FROM debian:12.9-slim AS engine-slim -COPY --from=builder /app/dist/rivet-server /usr/bin/rivet-server +LABEL org.opencontainers.image.source https://github.com/rivet-gg/rivet -CMD ["/usr/bin/rivet-server"] +# Docker automatically provides TARGETARCH +ARG TARGETARCH -# MARK: Edge server -FROM server-full-base AS edge-server - -COPY --from=builder /app/dist/rivet-edge-server /usr/bin - -CMD ["/usr/bin/rivet-edge-server"] - -# MARK: Rivet Guard -FROM server-full-base AS rivet-guard - -COPY --from=builder /app/dist/rivet-guard /usr/bin/rivet-guard - -CMD ["/usr/bin/rivet-guard"] - -# MARK: Runner base -FROM --platform=linux/amd64 debian:12.9-slim AS base-runner ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update -y && \ - apt-get install -y ca-certificates openssl curl tini curl && \ - curl -Lf -o /lib/libfdb_c.so "https://github.com/apple/foundationdb/releases/download/7.1.60/libfdb_c.x86_64.so" - -# MARK: Runner (Slim) -FROM --platform=linux/amd64 base-runner AS client-slim -ARG CNI_PLUGINS_VERSION=1.3.0 -RUN apt-get install -y skopeo iproute2 runc dnsutils && \ - echo "Downloading lz4" && \ - curl -L https://releases.rivet.gg/tools/lz4/1.10.0/debian11-amd64/lz4 -o /usr/local/bin/lz4 && \ - chmod +x /usr/local/bin/lz4 && \ - echo "Downloading umoci" && \ - curl -Lf -o /usr/bin/umoci "https://github.com/opencontainers/umoci/releases/download/v0.4.7/umoci.amd64" && \ - chmod +x /usr/bin/umoci && \ - echo "Downloading cnitool" && \ - curl -Lf -o /usr/bin/cnitool "https://github.com/rivet-gg/cni/releases/download/v1.1.2-build3/cnitool" && \ - chmod +x /usr/bin/cnitool && \ - echo "Downloading cni-plugins" && \ - mkdir -p /opt/cni/bin /opt/cni/config && \ - curl -L https://github.com/containernetworking/plugins/releases/download/v${CNI_PLUGINS_VERSION}/cni-plugins-linux-amd64-v${CNI_PLUGINS_VERSION}.tgz | \ - tar -xz -C /opt/cni/bin -COPY --chmod=755 ./docker/dev-full/rivet-client/entrypoint.sh /usr/local/bin/entrypoint.sh -COPY ./docker/dev-full/rivet-client/rivet-actor.conflist /opt/cni/config/rivet-actor.conflist -COPY --from=builder /app/dist/rivet-client /app/dist/rivet-container-runner /usr/local/bin/ -ENTRYPOINT ["/usr/bin/tini", "--", "entrypoint.sh"] - -# MARK: Runner (Full) -FROM client-slim AS client-full -ARG CADVISOR_VERSION=v0.52.0 -RUN apt-get update -y && \ - apt-get install -y wget && \ - wget -O /usr/local/bin/cadvisor "https://github.com/google/cadvisor/releases/download/${CADVISOR_VERSION}/cadvisor-${CADVISOR_VERSION}-linux-amd64" && \ - chmod +x /usr/local/bin/cadvisor && \ + apt-get install -y ca-certificates openssl curl && \ apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -COPY docker/universal/client-full-entrypoint.sh /usr/local/bin/client-full-entrypoint.sh -RUN chmod +x /usr/local/bin/client-full-entrypoint.sh - -ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/client-full-entrypoint.sh"] - -# MARK: Monlith -FROM --platform=linux/amd64 debian:12.9-slim AS monolith -ENV DEBIAN_FRONTEND=noninteractive - -ARG TRAEFIK_VERSION=3.2.1 -ARG COCKROACHDB_VERSION=24.2.3 -ARG NATS_VERSION=2.9.2 -ARG SEAWEEDFS_VERSION=3.79 -# See docs-internal/infrastructure/fdb/AVX.md -ARG FDB_VERSION=7.1.60 -ARG VECTOR_VERSION=0.42.0 -ARG S6_OVERLAY_VERSION=3.2.0.2 - -# === Install === -COPY ./docker/monolith/build-scripts /tmp/build-scripts -# Remove the scripts after running since this pulls dependencies for Deno. -RUN /tmp/build-scripts/install.sh && rm -r /tmp/build-scripts - -# === Copy Configs === -COPY ./docker/monolith/run-scripts/ /root/run-scripts - -COPY ./docker/monolith/clickhouse/config.xml /etc/clickhouse-server/config.d/config.xml -COPY ./docker/monolith/clickhouse/users.xml /etc/clickhouse-server/users.d/users.xml - -COPY ./docker/monolith/seaweedfs /etc/seaweedfs - -COPY ./docker/monolith/foundationdb/etc /etc/foundationdb -COPY --chmod=0755 ./docker/monolith/foundationdb/entrypoint.sh /usr/local/bin/foundationdb-entrypoint.sh - -COPY ./docker/monolith/vector-client /etc/vector-client -COPY ./docker/monolith/vector-server /etc/vector-server - -COPY ./docker/monolith/rivet-server /etc/rivet-server - -COPY ./docker/monolith/rivet-guard /etc/rivet-guard - -COPY ./docker/monolith/rivet-client /etc/rivet-client - -# === Copy Build Artifacts === -COPY --from=builder /app/dist/rivet-server /usr/local/bin/ -COPY --from=builder /app/dist/rivet-client /app/dist/rivet-isolate-v8-runner /app/dist/rivet-container-runner /usr/local/bin/ - -VOLUME ["/data"] - -EXPOSE 8080 8081 8082 7080 7443 7500-7599 7600-7699 - -ENV S6_LOGGING=1 -ENV S6_VERBOSITY=1 -ENV S6_KILL_GRACETIME=100 -ENV S6_KILL_FINISH_MAXTIME=100 + rm -rf /var/lib/apt/lists/* && \ + if [ "$TARGETARCH" = "arm64" ]; then \ + curl -Lf -o /lib/libfdb_c.so "https://github.com/apple/foundationdb/releases/download/7.3.68/libfdb_c.aarch64.so"; \ + else \ + curl -Lf -o /lib/libfdb_c.so "https://github.com/apple/foundationdb/releases/download/7.3.68/libfdb_c.x86_64.so"; \ + fi -ENTRYPOINT ["/init"] +COPY --from=builder /app/dist/rivet-engine /usr/bin/rivet-engine +CMD ["/usr/bin/rivet-engine", "start"] diff --git a/docker/universal/client-full-entrypoint.sh b/docker/universal/client-full-entrypoint.sh deleted file mode 100644 index a08d6b138e..0000000000 --- a/docker/universal/client-full-entrypoint.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -set -e - -# Start cadvisor in the background -cadvisor \ - --port=7780 \ - --listen_ip=0.0.0.0 \ - --prometheus_endpoint="/metrics" \ - --enable_metrics=cpu,cpuLoad,memory,network,disk,diskIO,oom_event,process,tcp,udp \ - --docker_only=false \ - --disable_root_cgroup_stats=false & - -# TODO: -# --raw_cgroup_prefix_whitelist="" \ - -# Start rivet-client with all passed arguments -exec rivet-client "$@" diff --git a/docker/workspace/Dockerfile b/docker/workspace/Dockerfile deleted file mode 100644 index c2a7061eea..0000000000 --- a/docker/workspace/Dockerfile +++ /dev/null @@ -1,28 +0,0 @@ -FROM debian:12.9 - -RUN apt-get update && apt-get install -y \ - curl \ - sudo \ - xz-utils \ - && rm -rf /var/lib/apt/lists/* - -RUN echo '#!/bin/bash\nexec nix-shell /app/shell.nix "$@"' > /usr/local/bin/nix-shell-wrapper && chmod +x /usr/local/bin/nix-shell-wrapper - -RUN useradd -m nixuser && echo "nixuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/nixuser - -USER nixuser - -RUN curl -vL https://nixos.org/nix/install | sh - -ENV USER nixuser -ENV PATH /home/nixuser/.nix-profile/bin:/home/nixuser/.nix-profile/sbin:/nix/var/nix/profiles/default/bin:/nix/var/nix/profiles/default/sbin:$PATH -ENV NIX_PATH /nix/var/nix/profiles/per-user/nixuser/channels - -WORKDIR /app - -COPY --chown=nixuser:nixuser shell.nix /app/ - -RUN nix-shell shell.nix --run "true" - -ENTRYPOINT ["/usr/local/bin/nix-shell-wrapper"] - diff --git a/docker/workspace/Dockerfile.dockerignore b/docker/workspace/Dockerfile.dockerignore deleted file mode 100644 index 559656bc90..0000000000 --- a/docker/workspace/Dockerfile.dockerignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!shell.nix diff --git a/docs b/docs deleted file mode 120000 index 4759ea83c9..0000000000 --- a/docs +++ /dev/null @@ -1 +0,0 @@ -site/src/content/docs/ \ No newline at end of file diff --git a/docs-internal/development/DEBUGGING.md b/docs-internal/development/DEBUGGING.md deleted file mode 100644 index 6f463c420c..0000000000 --- a/docs-internal/development/DEBUGGING.md +++ /dev/null @@ -1,135 +0,0 @@ -# Debugging - -## Logging filter - -Logging is implemented using Tracing's [`EnvFilter`](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html). - -This filter can be configured by setting the `RUST_LOG` environment variable. - -To enable all debug logging, set the env var: `RUST_LOG=debug` - -For example, to enable debug logging for the `cluster` crate, set the env var: `RUST_LOG=cluster=debug` - -Read more on how to use the filter [here](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html). - -# Tracing instruments - -Every log has a stack trace associated with it. This is not a native Rust backtrace; instead this is a backtrace to any function with `#[tracing::instrument]` defined on it. - -This allows us to understand where logs came from without incurring the overhead of Rust's native backtraces. - -# Tokio console - -Tokio Console can be enabled by setting the env var `TOKIO_CONSOLE_ENABLE=1` and visiting 127.0.0.1:6669. This address can be overridden with `TOKIO_CONSOLE_BIND`. - -# Logging properties - -- `RUST_LOG` (see [`EnvFilter`](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html)) -- `TOKIO_CONSOLE_ENABLE` -- `TOKIO_CONSOLE_BIND` -- `RUST_LOG_SPAN_NAME` -- `RUST_LOG_SPAN_PATH` -- `RUST_LOG_TARGET` -- `RUST_LOG_LOCATION` -- `RUST_LOG_MODULE_PATH` -- `RUST_LOG_ANSI_COLOR` - -## Reading logs - -Rivet uses structured logging, which can be verbose and hard to read at times. - -Here is an example log: - -```json -{ - "timestamp": "2023-11-14T20:24:34.038004Z", - "level": "INFO", - "fields": { - "message": "operation call", - "body": "Request { user_ids: [Uuid(6bda49ad-355c-4f0b-b76f-cb773f4ba9df)] }" - }, - "target": "rivet_operation", - "spans": [ - { - "method": "GET", - "ray_id": "f14d9ff6-06bf-42dc-8939-8e228c4baa0f", - "uri": "/cloud/games?watch_index=1699993473573", - "name": "http request" - }, - { "operation": "user-get", "name": "call" } - ] -} -``` - -- `target` is the name of the span (usually the function name) that made the log -- `fields` are the relevant information to the given function call -- `spans` are an abbreviated stack trace providing information about where the log came from - - `spans[0].ray_id` is important, see below - -### Parsing & formatting logs - -Loki's [`json`](https://grafana.com/docs/loki/latest/query/log_queries/#parser-expression) parser and -[`line_format`](https://grafana.com/docs/loki/latest/query/log_queries/#line-format-expression) expression are -helpful for parsing structured logs. - -## Rays & requests - -Any code that runs in Rivet has an associated ray ID & request ID. These IDs are UUIDs generated by Rivet, not -by an external provider. - -A ray correlates a series of actions that started from a single event (such as an HTTP request or CRON job). - -A request represents what happens in a single `OperationContext` (e.g. operation call, consuming a message, -HTTP request). - -There are multiple requests for a single ray. - -### Querying by ray - -When running in to any issue, the first thing you want to do is find the ray ID that this issue came from. - -Use that ray ID and query Loki with the following: - -``` -{name=~"rivet-.*"} |= "ead90acf-8a95-43c8-9c8b-8671fb373cca" -``` - -This will give you all logs associated with the problem. From here, you can either narrow down the service or -filter by errors. - -### Helpful log messages - -The following log messages are commonly queried against in Loki to narrow down events: - -- `operation call` provides the request for an operation -- `operation response` provides the response for an operation -- `publish message` provides the source & body of a published message -- `received message` is logged when workers consume a message -- `worker success` is logged when a worker finishes - -## Testing - -Rivet is extensively tested, which makes it easy to narrow down the cause of an error. - -### Reading test logs - -Use `cat` to read the logs at the given path. If wish to read the logs in real time, use -`tail -f `. - -Test logs are also available in Loki. - -## Monitoring performance & errors - -Rivet exposes extensive Prometheus metrics on our internal services. Look for the following Grafana -dashboards: - -- `Chirp / API` for performance & errors on API services -- `Chirp / Operation` for performance, errors, & consumer monitoring on operations & consumers -- `Chirp / Perf Spans` for performance of narrow portions of services -- `Rivet / SQL` for monitoring SQL queries & pools - -## Alerting - -Rivet uses Grafana Alerts for catching errors before they happen & quickly narrowing down the -source of errors. Alerts can be pushed to Slack if the `grafana_alerts/slack/webhook_url` secret is provided. -See _infra/tf/k8s_infra/prometheus.tf_. diff --git a/docs-internal/development/FRONTEND.md b/docs-internal/development/FRONTEND.md deleted file mode 100644 index 3faf7d07f5..0000000000 --- a/docs-internal/development/FRONTEND.md +++ /dev/null @@ -1,44 +0,0 @@ -# Frontend Development - -## Overview - -The "Frontend" part of this repository consist of: -- Hub (hub.rivet.gg) ([frontend/apps/hub](https://github.com/rivet-gg/rivet/tree/main/frontend/apps/hub)) -- Site (rivet.gg) ([site](https://github.com/rivet-gg/rivet/tree/main/site)) -- Actors SDK ([sdks/actor](https://github.com/rivet-gg/rivet/tree/main/sdks/actor)) - -For more information check README.md in the desired directory. - -## Development - -### Prerequisites -- Node.js (>=18.19) -- Yarn (use [Corepack](https://nodejs.org/api/corepack.html)) - - -### Setup - -1. Clone the repository -2. Install dependencies - ```bash - yarn - ``` -3. Start the development server - ```bash - yarn start - ``` - -### Build -1. Build the project - ```bash - yarn build - ``` - 1. You can define what app should be built using the `--filter` flag - ```bash - yarn build --filter=./site - ``` - -### Code Quality - -Don't worry about code quality, we got you covered! We use https://autofix.ci/ to automatically fix and format your code. - diff --git a/docs-internal/development/INTERNAL_EXTERNAL_ALIASES.md b/docs-internal/development/INTERNAL_EXTERNAL_ALIASES.md deleted file mode 100644 index f57bd7e788..0000000000 --- a/docs-internal/development/INTERNAL_EXTERNAL_ALIASES.md +++ /dev/null @@ -1,18 +0,0 @@ -# Internal <-> External Naming Aliases - -Most internal types have different names than what's exposed in the public API. - -This allos us to start devleoping functionality internally and decide the best name for DX after the fact. - -## Aliases - -| Internal | External | Notes | -| ---------------------------------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `ds` (Dynamic Server) & Pegboard `actor` | Actors | `ds` glues together `cluster` and `pegboard` | -| `pegboard` | Orchestrator | | -| `pegboard-manager` | Rivet Client | | -| Region | Datacenter | Regions will eventually be split from datacenters internally for failover support. This will not be a breaking change since we refer to regions by the datacenter name ID. We currently have an internal `region` package, but this is deprecated. | -| `team` | Developer Team | | -| `identity` | User | | -| `game` | Project | | -| `namespace` | Environment | | diff --git a/docs-internal/development/NAMING_CONVENTIONS.md b/docs-internal/development/NAMING_CONVENTIONS.md deleted file mode 100644 index b9dc48711e..0000000000 --- a/docs-internal/development/NAMING_CONVENTIONS.md +++ /dev/null @@ -1,102 +0,0 @@ -# Naming Conventions - -> **Most internal APIs are not standardized** -> -> For reference, follow the conventions in `api-actor`. - -## APIs, Operations, & Workflows - -### Internal & external names - -Internal & external names are often different. Convert the names on the API server. Do not expose internal names to the API. Make sure formatted errors also comply to the same type names. - -See alias mappings [here](./INTERNAL_EXTERNAL_ALIASES.md). - -### Legacy terms - -- `{self}_id` -> `id` (e.g. `Actor.actor_id` -> `Actor.id`) -- `{some_type}_id` -> `{some_type}` (e.g. `Actor.datacenter_id` -> `Actor.datacenter`) -- `name_id` -> `slug` -- `display_name` -> `name` -- `{}_ts` -> `{}_at` (e.g. `created_ts` -> `created_at`) - -### Request & response parameters - -- Timestamps end with `at`. Use the past tense of the verb. For example, `createdAt` and `expiredAt`. -- Prefer enums instead of boolean. For example, instead of `completed: boolean`, use `status: "completed" | "started"`. -- Use optional timestamps instead of booleans. For example, instead of `completed: boolean`, use `completedAt?: number`. -- Refer to the ID of the current object as just `id` (not something like `user_id`). -- Do not use `id` in the variable name if passing an id. For example, use `datacenter` instead of `datacenter_id`. - - If storing an ID, make sure that the variable name references the name of the corresponding data. For example `owner_user` -> `User` or `datacenter` -> `Datacenter`. -- Format dates with RFC 3339 (which is a profile of ISO 8601) in the format of `2024-07-06T04:56:49.517Z`. This provides a balance of human-readable & machine-readable dates. - - Do not include timezones in dates. Always use UTC with `Z` (not `+00:00`). - - Include milliseconds in dates. -- Common property names: - - `id` Sometimes a UUID, sometimes a slug. e.g. datacenters use a string for the ID, but actors use a UUID. This is because actors are created by users & aren't usually referenced by name. - - `created_at` & `destroyed_at` - - `name` Used for human-readable name. - - `slug` If there is a short string used to refer to this object. Only use this if not already used for the UUID. e.g. datacenters use a string for the ID. -- Format durations in milliseconds, except in the uncommon case of performance-sensitive code. In that case, use microseconds. -- For any other cases, delegate to [Stripe's naming semantics](https://docs.stripe.com/api/customers). - -### Camel case + acryonyms - -Follow camel case strictly & treat acronyms as single words. - -Examples: - -- Prefer `Uuid` instead of `UUID` -- Prefer `OpenApi` instead of `OpenAPI` - -### Externally tagged enums - -When representing an enum with associated data (often called "sum types" which are a kind of algebreic data type, ADT), represent using a nested object (often called "externally tagged enums"). - -This comes at the expense of not having exhaustive switch statements. - -Externally tagged enums are easy to represent in languages that don't support advanced type constraints, such as C# and most OpenAPI SDK generators (i.e. don't support `oneOf`). - -This example: - -```typescript -type MyEnum = { foo: MyEnumFoo } | { bar: MyEnumBar } | { baz: MyEnumBaz }; - -interface MyEnumFoo { - -} - -interface MyEnumBar { - -} - -interface MyEnumBaz { - -} -``` - -Can be represented in C# like this: - -```csharp -class MyEnum { - MyEnumFoo? Foo; - MyEnumBar? Bar; - MyEnumBaz? Baz; -} - -class MyEnumFoo { -} - -class MyEnumBar { -} - -class MyEnumBaz { -} -``` - -## Databases - -### Uses of `id` included with type - -When referring to the ID of the current type, use `id`. When referring to a -foreign type, use `{type name}Id`. - diff --git a/docs-internal/development/TROUBLESHOOTING.md b/docs-internal/development/TROUBLESHOOTING.md deleted file mode 100644 index 1f71719822..0000000000 --- a/docs-internal/development/TROUBLESHOOTING.md +++ /dev/null @@ -1,31 +0,0 @@ -# Troubleshooting - -## `failed to solve` - -The following indicates that you've ran out of disk space. - -``` -84.84 rustc-LLVM ERROR: IO failure on output stream: No space left on device -...etc... -90.32 error: could not compile `xxxx` (lib); 1 warning emitted ------- -failed to solve: process "/bin/sh -c RUSTFLAGS=\"--cfg tokio_unstable\" cargo build --bin rivet-server && \tmv target/debug/rivet-server /usr/bin/rivet-server && \tmkdir /etc/rivet-server" did not complete successfully: exit code: 101 -``` - -## `error: linking with `cc` failed: exit status: 1` - -The following indicates that the process was force killed (`signal 9`), which usually indicates you've ran out of memory. - -``` -2.246 Compiling rivet-server v0.0.1 (/app/packages/infra/server) -55.18 error: linking with `cc` failed: exit status: 1 -...etc... -55.18 = note: collect2: fatal error: ld terminated with signal 9 [Killed] -55.18 compilation terminated. -55.18 -55.18 -55.35 error: could not compile `rivet-server` (bin "rivet-server") due to 1 previous error -``` - -If you're using `docker compose up --build`, try building one service at a time. Building multiple Rust binaries at the same time will eat a lot of memory. - diff --git a/docs-internal/infrastructure/SBOM.md b/docs-internal/infrastructure/SBOM.md deleted file mode 100644 index 38b637b9ea..0000000000 --- a/docs-internal/infrastructure/SBOM.md +++ /dev/null @@ -1,41 +0,0 @@ -# Software Bill of Materials - -## Rust packages - -License policies are defined in `deny.toml`. - -Run the following: - -```bash -cargo deny --manifest-path svc/Cargo.toml list -``` - -## Infrastructure - -_Loosely follows [SPDX](https://spdx.org/licenses/) format._ - -| Software | License | -| --------------------- | ---------------------------------- | -| Apache Traffic Server | Apache-2.0 | -| CNI | Apache-2.0 | -| ClickHouse | Apache-2.0 | -| Cloudflared | | -| Cockroach | Apache-2.0 | -| Docker | Apache-2.0 | -| Imagor | Apache-2.0 | -| Minio | AGPL-3.0 (non-derivative, dev use) | -| NATS | Apache-2.0 | -| Node Exporter | Apache-2.0 | -| Nomad | MPL-2.0 | -| Prometheus | Apache-2.0 | -| Redis Exporter | MIT | -| Redis | BSD-3 | -| Terraform | Apache-2.0 | -| Traefik | MIT | -| cloudflared | Apache-2.0 | -| curl | curl | -| go-migrate | MIT | -| jq | MIT | -| nsfw_api | Apache-2.0 | -| open_nsfw | Apache-2.0 | -| rsync | GPL-3.0 (non-derivative) | diff --git a/docs-internal/infrastructure/TIMEOUTS.md b/docs-internal/infrastructure/TIMEOUTS.md deleted file mode 100644 index 33cdc01b5a..0000000000 --- a/docs-internal/infrastructure/TIMEOUTS.md +++ /dev/null @@ -1,76 +0,0 @@ -# Timeouts - -Many load balancers have 60s configured as default timeout. Our API timeouts are designed to work within these -bounds. - -## Preface: How network reaches Rivet - -``` -Client -> Cloudflare -> NLB -> Traefik -> api-monolith -``` - -## Infra timeouts - -These are the timeouts that our API servers are restricted to: - -- Cloudflare: 100s - ([source](https://developers.cloudflare.com/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-5xx-errors/#error-524-a-timeout-occurred)) - - **Behavior** Returns a 524 - - Cannot be configured unless paying for Cloudflare Enterprise -- AWS NAT Gateway: 350 seconds idle (without keepalive) - ([source](https://docs.aws.amazon.com/vpc/latest/userguide/nat-gateway-troubleshooting.html#nat-gateway-troubleshooting-timeout)) - - **Behavior** Connection drop -- AWS NLB: 350 seconds - ([source](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/network-load-balancers.html#connection-idle-timeout)) - - **Behavior** Connection drop -- Traefik: 60s, 120s - ([source](https://github.com/rivet-gg/rivet/blob/c63067ce6e81f97b435e424e576fbd922b14f748/infra/tf/k8s_infra/traefik.tf#L65)) - - **Behavior** _Unknown_ - - Unlike the other timeouts, this is configurable by us - - 60s timeout for active requests before traefik stops - - 120s timeout for reading the body and writing the response -- ATS (Through Traefik): 15s - ([source](https://github.com/rivet-gg/rivet/blob/01-26-Add_timeouts_max_in_flight_compression_to_API_and_CDN/infra/tf/k8s_infra/traffic_server.tf#L313)) - - **Behavior** _Unknown_ - -## Rivet API Timeouts - -We use long polling (i.e. `watch_index`) to implement real time functionality. This means we need to be -cautious about existing timeouts. - -Current timeouts: - -- `api-helper`: 50s - ([source](https://github.com/rivet-gg/rivet/blob/9811ae11656d63e26b4814fe15f7f852f5479a48/lib/api-helper/macros/src/lib.rs#L975)) - - **Behavior** Returns `API_REQUEST_TIMEOUT` - - **Motivation** This gives a 10s budget for any other 60s timeout -- `select_with_timeout!`: 40s - ([source](https://github.com/rivet-gg/rivet/blob/9811ae11656d63e26b4814fe15f7f852f5479a48/lib/util/macros/src/lib.rs#L12)) - - **Behavior** Timeout handled by API endpoint, usually 200 - - **Motivation** This gives a 10s budget for any requests before/after the select statement -- `tail!` and `tail_all!`: 40s (depending on `TailAllConfig`) - ([source](https://github.com/rivet-gg/rivet/blob/9811ae11656d63e26b4814fe15f7f852f5479a48/lib/util/macros/src/lib.rs#L12)) - - **Behavior** Timeout handled by API endpoint, usually 200 - - **Motivation** This gives a 10s budget for any requests before/after the select statement - -## Database connections - -### CockroachDB - -- `idle_timeout` is set to 3 minutes, which is less than the NAT Gateway timeout -- `test_before_acquire` is left as true in order to ensure we don't run in to timeouts, even though this adds - significant overhead - -### Redis - -- We ping the database manually every 15 seconds -- Back off retries is set to infinity in order to ensure that `ConnectionManager` always returns to a valid - state no matter the connection issues - - The current internal logic will cause the Redis connection to fail after 6 automatic disconnects, which - will cause the cluster to fail if idle for too long - -### Misc Resources - -- [Implementing long-running TCP Connections within VPC networking](https://aws.amazon.com/blogs/networking-and-content-delivery/implementing-long-running-tcp-connections-within-vpc-networking/) -- [Introducing configurable Idle timeout for Connection tracking](https://aws.amazon.com/blogs/networking-and-content-delivery/introducing-configurable-idle-timeout-for-connection-tracking/) - (this is intentionally not configured) diff --git a/docs-internal/infrastructure/clickhouse/TROUBLESHOOTING.md b/docs-internal/infrastructure/clickhouse/TROUBLESHOOTING.md deleted file mode 100644 index 8d561574cb..0000000000 --- a/docs-internal/infrastructure/clickhouse/TROUBLESHOOTING.md +++ /dev/null @@ -1,20 +0,0 @@ -# Troubleshooting - -## `Missing columns: 'xxxx' while processing query` in JSON - -In a query like this, where `properties` is `JSON`: - -``` -> SELECT properties.abc FROM events -Code: 47. DB::Exception: Received from clickhouse.clickhouse.svc.cluster.local:9440. DB::Exception: Missing columns: 'properties.abc' while processing query: 'SELECT properties.abc FROM events', required columns: 'properties.abc', maybe you meant: 'properties'. (UNKNOWN_IDENTIFIER) -``` - -This is because the `JSON` type is semi-structured and stored as a tuple under the hood. If there is not a row -with the given JSON property, then the tuple element will not exist. - -In order to optionally read a tuple element, you need to use `tupleElement`, like this (where `''` is the -fallback value): - -``` -SELECT tupleElement(properties, 'abc', '') FROM events -``` diff --git a/docs-internal/infrastructure/clickhouse/WHY_CLICKHOUSE.md b/docs-internal/infrastructure/clickhouse/WHY_CLICKHOUSE.md deleted file mode 100644 index c09ca8b22b..0000000000 --- a/docs-internal/infrastructure/clickhouse/WHY_CLICKHOUSE.md +++ /dev/null @@ -1,96 +0,0 @@ -# Why ClickHouse? - -## Motivation - -Rivet has a series of OLAP use cases, such as analytics, log aggregation, and more. - -## Requirements - -- Self hostable -- Easy to operate -- Realtime aggregates -- Cost effective -- Turnkey aggregation to avoid the TCO of a stream/batch processing framework - -### Nice to haves - -- Tiered storage -- Maintain a similar workflow to CockroachDB - -## Alternatives - -### CockroachDB - -We already run CockroachDB, so it makes sense to push it to its limit until it can't scale any more. - -**Vectorized execution** - -CockroachDB supports -[vectorized execution](https://www.cockroachlabs.com/docs/stable/vectorized-execution.html) in order to -optimize for some of the aggregating workloads that we use today in ClickHouse. This takes advantage of -similar mechanics you find in -[column-oriented databases](https://clickhouse.com/docs/en/faq/general/columnar-database) within an OLTP -database. However, Cokroach will never be architected as a column-oriented database to achieve the same -performance as ClickHouse. - -**Ingestion** - -We need to ingest large amounts of logs and analytics events in Rivet. While there has been a lot of work -[invested in ingestion performance](https://www.cockroachlabs.com/blog/bulk-data-import/), the hardware -required to achieve similar ingestion rates to ClickHouse is much more expensive. - -ClickHouse ingestion rates are 4.4x faster and take 5.3x less storage space that Postgres. - -**Benchmarks** - -While comparing benchmarks to Postgres is not quite a fair comparison, it's a _close enough_ comparison to -Cockroach's performance given they have similar design constraints. More work should be done to compare the -two head to head. - -[ClickHouse <-> Postgres benchmarks](https://benchmark.clickhouse.com/#eyJzeXN0ZW0iOnsiQXRoZW5hIChwYXJ0aXRpb25lZCkiOmZhbHNlLCJBdGhlbmEgKHNpbmdsZSkiOmZhbHNlLCJBdXJvcmEgZm9yIE15U1FMIjpmYWxzZSwiQXVyb3JhIGZvciBQb3N0Z3JlU1FMIjpmYWxzZSwiQnl0ZUhvdXNlIjpmYWxzZSwiY2hEQiI6ZmFsc2UsIkNpdHVzIjpmYWxzZSwiQ2xpY2tIb3VzZSAoZGF0YSBsYWtlLCBwYXJ0aXRpb25lZCkiOmZhbHNlLCJDbGlja0hvdXNlIChQYXJxdWV0LCBwYXJ0aXRpb25lZCkiOmZhbHNlLCJDbGlja0hvdXNlIChQYXJxdWV0LCBzaW5nbGUpIjpmYWxzZSwiQ2xpY2tIb3VzZSI6dHJ1ZSwiQ2xpY2tIb3VzZSAodHVuZWQpIjp0cnVlLCJDbGlja0hvdXNlICh6c3RkKSI6ZmFsc2UsIkNsaWNrSG91c2UgQ2xvdWQiOmZhbHNlLCJDbGlja0hvdXNlIENsb3VkIChBV1MpIjpmYWxzZSwiQ2xpY2tIb3VzZSBDbG91ZCAoR0NQKSI6ZmFsc2UsIkNsaWNrSG91c2UgKHdlYikiOmZhbHNlLCJDcmF0ZURCIjpmYWxzZSwiRGF0YWJlbmQiOmZhbHNlLCJEYXRhRnVzaW9uIChzaW5nbGUgcGFycXVldCkiOmZhbHNlLCJBcGFjaGUgRG9yaXMiOmZhbHNlLCJEcnVpZCI6ZmFsc2UsIkR1Y2tEQiAoUGFycXVldCwgcGFydGl0aW9uZWQpIjpmYWxzZSwiRHVja0RCIjpmYWxzZSwiRWxhc3RpY3NlYXJjaCI6ZmFsc2UsIkVsYXN0aWNzZWFyY2ggKHR1bmVkKSI6ZmFsc2UsIkdyZWVucGx1bSI6ZmFsc2UsIkhlYXZ5QUkiOmZhbHNlLCJIeWRyYSI6ZmFsc2UsIkluZm9icmlnaHQiOmZhbHNlLCJLaW5ldGljYSI6ZmFsc2UsIk1hcmlhREIgQ29sdW1uU3RvcmUiOmZhbHNlLCJNYXJpYURCIjpmYWxzZSwiTW9uZXREQiI6ZmFsc2UsIk1vbmdvREIiOmZhbHNlLCJNeVNRTCAoTXlJU0FNKSI6ZmFsc2UsIk15U1FMIjpmYWxzZSwiUGlub3QiOmZhbHNlLCJQb3N0Z3JlU1FMIjp0cnVlLCJQb3N0Z3JlU1FMICh0dW5lZCkiOnRydWUsIlF1ZXN0REIgKHBhcnRpdGlvbmVkKSI6ZmFsc2UsIlF1ZXN0REIiOmZhbHNlLCJSZWRzaGlmdCI6ZmFsc2UsIlNlbGVjdERCIjpmYWxzZSwiU2luZ2xlU3RvcmUiOmZhbHNlLCJTbm93Zmxha2UiOmZhbHNlLCJTUUxpdGUiOmZhbHNlLCJTdGFyUm9ja3MiOmZhbHNlLCJUaW1lc2NhbGVEQiAoY29tcHJlc3Npb24pIjpmYWxzZSwiVGltZXNjYWxlREIiOmZhbHNlfSwidHlwZSI6eyJzdGF0ZWxlc3MiOnRydWUsIm1hbmFnZWQiOnRydWUsIkphdmEiOnRydWUsImNvbHVtbi1vcmllbnRlZCI6dHJ1ZSwiQysrIjp0cnVlLCJNeVNRTCBjb21wYXRpYmxlIjp0cnVlLCJyb3ctb3JpZW50ZWQiOnRydWUsIkMiOnRydWUsIlBvc3RncmVTUUwgY29tcGF0aWJsZSI6dHJ1ZSwiQ2xpY2tIb3VzZSBkZXJpdmF0aXZlIjp0cnVlLCJlbWJlZGRlZCI6dHJ1ZSwiYXdzIjp0cnVlLCJnY3AiOnRydWUsInNlcnZlcmxlc3MiOnRydWUsIlJ1c3QiOnRydWUsInNlYXJjaCI6dHJ1ZSwiZG9jdW1lbnQiOnRydWUsInRpbWUtc2VyaWVzIjp0cnVlfSwibWFjaGluZSI6eyJzZXJ2ZXJsZXNzIjpmYWxzZSwiMTZhY3UiOmZhbHNlLCJMIjpmYWxzZSwiTSI6ZmFsc2UsIlMiOmZhbHNlLCJYUyI6ZmFsc2UsImM2YS40eGxhcmdlLCA1MDBnYiBncDIiOnRydWUsImM2YS5tZXRhbCwgNTAwZ2IgZ3AyIjpmYWxzZSwiYzUuNHhsYXJnZSwgNTAwZ2IgZ3AyIjpmYWxzZSwiNjAgdGhyZWFkcyAoaWRlYWwpIjpmYWxzZSwiNjAgdGhyZWFkcyAobG9jYWwpIjpmYWxzZSwiMTkyR0IiOmZhbHNlLCIyNEdCIjpmYWxzZSwiMzYwR0IiOmZhbHNlLCI0OEdCIjpmYWxzZSwiNzIwR0IiOmZhbHNlLCI5NkdCIjpmYWxzZSwiNzA4R0IiOmZhbHNlLCJtNWQuMjR4bGFyZ2UiOmZhbHNlLCJtNmkuMzJ4bGFyZ2UiOmZhbHNlLCJjNW4uNHhsYXJnZSwgNTAwZ2IgZ3AyIjpmYWxzZSwiYzZhLjR4bGFyZ2UsIDE1MDBnYiBncDIiOmZhbHNlLCJkYzIuOHhsYXJnZSI6ZmFsc2UsInJhMy4xNnhsYXJnZSI6ZmFsc2UsInJhMy40eGxhcmdlIjpmYWxzZSwicmEzLnhscGx1cyI6ZmFsc2UsIlMyNCI6ZmFsc2UsIlMyIjpmYWxzZSwiMlhMIjpmYWxzZSwiM1hMIjpmYWxzZSwiNFhMIjpmYWxzZSwiWEwiOmZhbHNlfSwiY2x1c3Rlcl9zaXplIjp7IjEiOnRydWUsIjIiOnRydWUsIjQiOnRydWUsIjgiOnRydWUsIjE2Ijp0cnVlLCIzMiI6dHJ1ZSwiNjQiOnRydWUsIjEyOCI6dHJ1ZSwic2VydmVybGVzcyI6dHJ1ZSwidW5kZWZpbmVkIjp0cnVlfSwibWV0cmljIjoiaG90IiwicXVlcmllcyI6W3RydWUsdHJ1ZSx0cnVlLHRydWUsdHJ1ZSx0cnVlLHRydWUsdHJ1ZSx0cnVlLHRydWUsdHJ1ZSx0cnVlLHRydWUsdHJ1ZSx0cnVlLHRydWUsdHJ1ZSx0cnVlLHRydWUsdHJ1ZSx0cnVlLHRydWUsdHJ1ZSx0cnVlLHRydWUsdHJ1ZSx0cnVlLHRydWUsdHJ1ZSx0cnVlLHRydWUsdHJ1ZSx0cnVlLHRydWUsdHJ1ZSx0cnVlLHRydWUsdHJ1ZSx0cnVlLHRydWUsdHJ1ZSx0cnVlLHRydWVdfQ==) - -**Tiered storage** - -CockroachDB does not support tiered storage. - -### Time series database (e.g. InfluxDB, TimescaleDB) - -While a specialized TSDB would handle a lot of the use cases that we're using ClickHouse for, ClickHouse is a -much more flexible database. At this stage of a startup, taking on the TCO of multiple databases can be taxing -on management and complexity. - -### Batch processing (e.g. Spark) - -This does not provide realtime analytics. - -### Stream processing (e.g. Flink, Spark Realtime) - -While stream processing frameworks achieve many of the goals that we need, we're striving for simplicity. -These tools are notoriously difficult to operate. However, providers like Aiven provude managed versions of -this software at scale. - -ClickHouse also allows us to use the same migration tools (`go-migrate`) for both Cockroach and ClickHouse. -Ingesting data in to both are done in similar methods, so our architecture is kept simple and consistent. - -### OpenSearch - -> TODO - -### Apache Druid - -> TODO - -### Apache Pinot - -> TODO - -### Firebolt - -### Google BigQuery & Snowflake & Amazon Redshift - -These options are managed solutions that can't be self hosted. These are also incredibly expensive compared to -using raw hardware to run ClickHouse. - -## Shortcomings - -> TODO diff --git a/docs-internal/infrastructure/cockroach/README.md b/docs-internal/infrastructure/cockroach/README.md deleted file mode 100644 index 7996e64341..0000000000 --- a/docs-internal/infrastructure/cockroach/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# CockroachDB - -## What is CockroachDB? - -CockroachDB (referred to as "Cockroach" or "CRDB") is a Postgres-compatible SQL database built to run across -multiple nodes and regions. This lets us have a very flexible and fault tolerant architecture for our database -across multiple cloud providers and regions. - -## What do we use CockroachDB for? - -We use CockroachDB for all data that makes sense to be stored in an SQL database. diff --git a/docs-internal/infrastructure/cockroach/WHY_COCKRAOCH.md b/docs-internal/infrastructure/cockroach/WHY_COCKRAOCH.md deleted file mode 100644 index 2aa32286bb..0000000000 --- a/docs-internal/infrastructure/cockroach/WHY_COCKRAOCH.md +++ /dev/null @@ -1,80 +0,0 @@ -# Why CockroachDB? - -## Motivation - -Rivet needs a OLTP to provide the core of our operations. - -**Why SQL** - -KV & document databases like MongoDB are not an option. Databases that use good old SQL usually have -straightforward transaction processing, joins, constraints, schemas, and row locking mechanics that are often -well handled in other types of databases. - -Adopting an SQL-based database also means that developers don't have to learn the semantics of a new query -language and all the pitfalls that comes with it. - -SQL is an oldie but a godie. - -## Requirements - -- Easy to operate -- ACID-compliant-ish (distributed SQL databases often aren't truly ACID compliant) -- Schemas & constraints -- Secondary indexes - -## Alternatives - -### Postgres - -**Maturity & Governance** - -In hindsight, it would have been a good idea to stick with Postgres instead of building on top of CockroachDB, -which is a newer and for-profit database. - -**Exentions** - -While CockroachDB supports common features like JSON, full-text search, and spatial indexes, there are -numerous Postgres extensions that will never exists within CockroachDB. For example, we could have used the -TimescaleDB extension instead of ClickHouse for our time series workloads. If we chose to support ML -workloads, pgvector would be a click away, but instead we would have to adopt a new database. - -**Scaling\*** - -"It doesn't scale" is a common refrain for Postgres critics. Because CockroachDB is a distributed database, it -will scale much better that Postgres does. However, a startup that has to scale to that size will also have -the means to hire a team of engineers to handle that migration. Velocity is much more important at an early -stage, so choosing immature technologies tends to not be a good idea. Luckily, CockroachDB has been preditable -and reliable thus far. - -**Ease of operation** - -Postgres is not a difficult database to operate _but_ CockroachDB has a really powerful web interface that -provides monitoring, index insights, and much more. Additionally, adding and removing nodes form CockroachDB -is very straightfowrard. The claims of "you can't kill CockroachDB" have held up so far for us. - -**GDPR compliance** - -CockroachDB supports handling data locality natively while Postgres requires running a separate database for -European users. - -### FoundationDB - -> TODO - -### Vitess - -> TODO - -### YugaByte - -> TODO - -### Key-value database (e.g. Cassandra) - -> TODO - -## Shortcomings - -- Managed by a for-profit corporation which could go under or change the license (e.g. ElasticCache) -- Lack of Postgres-like extensions -- Lack of UDF diff --git a/docs-internal/infrastructure/fdb/AVX.md b/docs-internal/infrastructure/fdb/AVX.md deleted file mode 100644 index 5186e8254f..0000000000 --- a/docs-internal/infrastructure/fdb/AVX.md +++ /dev/null @@ -1,23 +0,0 @@ -# AVX - -AVX (Advanced Vector Extensions) is a SIMD instruction on Intel CPUs to make -FoundationDB run parallel data processing tasks faster. - -## Even & odd versions - -Even versions of FoundationDB are compiled without AVX. Odd versions are compiled with it. - -For example, [7.1.61](https://github.com/apple/foundationdb/releases/tag/7.1.61) is the AVX version of [7.1.60](https://github.com/apple/foundationdb/releases/tag/7.1.60). - -Make sure to pay attention to if you're using a version of FDB with AVX. - -## When to use AVX - -Use AVX on production Linux servers. - -## When not to use AVX - -Don't use AVX for Docker images, since QEMU can't emulate AVX and will crash ([source](https://github.com/apple/foundationdb/issues/4111#issuecomment-1284040423)). This will prevent ARM users from being able to run FoundationDB. - -This might be easy to fix if we build a Docker image built on the prebuilt AMD & ARM binaries on GitHub. - diff --git a/docs-internal/infrastructure/fdb/CLUSTER.md b/docs-internal/infrastructure/fdb/CLUSTER.md deleted file mode 100644 index 2cc151b4b8..0000000000 --- a/docs-internal/infrastructure/fdb/CLUSTER.md +++ /dev/null @@ -1,6 +0,0 @@ -# Cluster layout - -Ideally, 3 servers per DC that coordinate with each other. - -Each process should have around 4GB of memory, so servers with more than 4GB can run multiple processes -(unconfirmed). diff --git a/docs-internal/infrastructure/fdb/TROUBLESHOOTING.md b/docs-internal/infrastructure/fdb/TROUBLESHOOTING.md deleted file mode 100644 index 49f60f56f9..0000000000 --- a/docs-internal/infrastructure/fdb/TROUBLESHOOTING.md +++ /dev/null @@ -1,28 +0,0 @@ -# Troubleshooting - -## Cannot connect to cluster - -This may be caused by many reasons. - -### `fdb.cluster` does not match between client and host - -The client and host must be able to address the server with the same IP. - -Validate that the client config (e.g. `/var/lib/rivet-client/fdb.cluster` on a Rivet client) matches the file `/var/fdb/fdb.cluster` on the FoundationDB server. - -If you're using DNS to resolve the cluster, make sure that the DNS address resolves to the correct location. - -### `Illegal instruction` - -This usually means you're trying to use the AVX version of FoundationDB on an -unsupported system. This also happens when attempting to run AVX FoundationDB -on an Apple Silicon chip, since Docker's x86 emulation does not support AVX. - -See [here](./AVX.md) for more information. - -## `FdbBindingError::BadCode` - -This usually indicates that `unpack` was not correct. - -If reading ranges, double check that the subspace that the `unpack` from is what you expect. - diff --git a/docs-internal/infrastructure/github_actions/DEBUGGING.md b/docs-internal/infrastructure/github_actions/DEBUGGING.md deleted file mode 100644 index 60474d2c81..0000000000 --- a/docs-internal/infrastructure/github_actions/DEBUGGING.md +++ /dev/null @@ -1,16 +0,0 @@ -# Debugging - -## Testing release workflow - -It's common to need to test or iterate on the release workflow. - -Set `branch` to the current branch and `version` to `x.x.x-rc.x` for a release candidate. - -Make sure to disable the automatic merging of the Release Please commit. - -``` -gt m -a && gt s --force && gh workflow run .github/workflows/release.yaml --ref BRANCH -f version=VERSION -f latest=false -``` - -`--force` is because this workflow will push commits automatically. - diff --git a/docs-internal/infrastructure/helm/TROUBLESHOOTING.md b/docs-internal/infrastructure/helm/TROUBLESHOOTING.md deleted file mode 100644 index 17ca6cf2ef..0000000000 --- a/docs-internal/infrastructure/helm/TROUBLESHOOTING.md +++ /dev/null @@ -1,58 +0,0 @@ -# Troubleshooting - -## `Error: cannot re-use a name that is still in use` - -First, try uninstalling the chart manually with: - -``` -helm uninstall -n foo bar -``` - -If that doesn't work, check if there is a secret named something like `sh.helm.release.v1.bar.v1` in the given -namespace: - -``` -kubectl get secret -n foo -``` - -If so, delete the secret with: - -``` -kubectl delete secret -n foo foobar -``` - -Then re-run the Terraform plan. - -## `Error: another operation (install/upgrade/rollback) is in progress` - -Your helm deployment probabily failed. You need to roll it back. For example: - -Roll back to the last deployed revision: - -```sh -[nix-shell:/home/rivet/rivet-ee]# helm list -n promtail --all -NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION -promtail promtail 8 2025-03-06 01:17:04.451599765 +0000 UTC pending-upgrade promtail-6.15.1 2.8.4 - -[nix-shell:/home/rivet/rivet-ee]# helm -n promtail history promtail -REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION -1 Sun Oct 29 18:41:08 2023 superseded promtail-6.15.1 2.8.4 Install complete -2 Mon Nov 6 06:47:58 2023 superseded promtail-6.15.1 2.8.4 Upgrade complete -3 Sun Feb 4 21:23:30 2024 superseded promtail-6.15.1 2.8.4 Upgrade complete -4 Mon Feb 5 19:57:21 2024 superseded promtail-6.15.1 2.8.4 Upgrade complete -5 Sat Feb 24 21:32:04 2024 superseded promtail-6.15.1 2.8.4 Upgrade complete -6 Mon May 20 23:57:18 2024 deployed promtail-6.15.1 2.8.4 Upgrade complete -7 Thu Mar 6 01:11:20 2025 failed promtail-6.15.1 2.8.4 Upgrade "promtail" failed: context deadline exceeded -8 Thu Mar 6 01:17:04 2025 pending-upgrade promtail-6.15.1 2.8.4 Preparing upgrade - -[nix-shell:/home/rivet/rivet-ee]# helm -n promtail rollback promtail 6 -Rollback was a success! Happy Helming! -``` - -Apply your Helm chart again: - -```sh -[nix-shell:/home/rivet/rivet-ee]# helm list -n promtail -NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION -promtail promtail 9 2025-03-06 01:28:52.820014049 +0000 UTC deployed promtail-6.15.1 2.8.4 -``` diff --git a/docs-internal/infrastructure/imagor/MEDIA_DELIVERY_AND_RESIZING.md b/docs-internal/infrastructure/imagor/MEDIA_DELIVERY_AND_RESIZING.md deleted file mode 100644 index 245e1fbac4..0000000000 --- a/docs-internal/infrastructure/imagor/MEDIA_DELIVERY_AND_RESIZING.md +++ /dev/null @@ -1,38 +0,0 @@ -# Media Deliver and Resizing - -## Architecture - -### Uploading - -We don't resize anything until the image is fetched. - -``` -Prepare: Browser -> upload-prepare -Upload: Browser -> Backblaze -Complete: Browser -> upload-complete -``` - -### Fetching - -Media is resized on demand when the client fetches it. - -``` -Browser -> Cloudflare -> Traefik -> Imagor (resizes) -> ATS (caches) -> Backblaze (storage) -``` - -1. Cloudflare serves requests with a cache -1. Traefik is responsible for expanding the URL in to the appropriate preset for Imagor (see below on DoS - protection) -1. Imagor will attempt to fetch the cached image. If it can't find it, it will fetch the master image and - resize and cache the resized image appropriately. -1. ATS will cache any images that were recently fetched from Backblaze -1. Backblaze is responsible for storing the master images - -## Prefixes for DoS Protection - -Vanilla Imagor allows for applying any arbitrary resize and filter to images. This enables attackers to -request large amounts of image resizes and cripples our caching layer. - -Treafik is configured to expose a pre-defined set of filter that get applied to the image and Treafik will -automatically prefix the URL with the correct filter. This way, attackers can't define their own filters and -we have a limited number of images we're responsible for resizing. diff --git a/docs-internal/infrastructure/legacy/fern/OSS_SETUP.md b/docs-internal/infrastructure/legacy/fern/OSS_SETUP.md deleted file mode 100644 index d5c4fcee05..0000000000 --- a/docs-internal/infrastructure/legacy/fern/OSS_SETUP.md +++ /dev/null @@ -1,28 +0,0 @@ -# Fern OSS Setup - -To install fern, first clone the repo and check out the branch - -```shell -$ git clone https://github.com/rivet-gg/fern -$ cd fern -$ git checkout max/remove-headers -``` - -Then, follow the instructions in SETUP.md and CONTRIBUTING.md to compile fern - -```shell -yarn -yarn compile -yarn dist:cli:dev -docker image ls | grep fern -docker builder prune -yarn workspace @fern-typescript/sdk-generator-cli run dockerTagVersion:browser 999.999.999 -yarn workspace @fern-api/openapi-generator run dockerTagVersion 999.999.999 -``` - -Finally, run this with the path to the fern repo, say: - -```shell -FERN_REPO_PATH=~/fern ./oss/scripts/fern/gen.sh -``` - diff --git a/docs-internal/infrastructure/legacy/protobuf/TIMESTAMPS.md b/docs-internal/infrastructure/legacy/protobuf/TIMESTAMPS.md deleted file mode 100644 index c5a1421d16..0000000000 --- a/docs-internal/infrastructure/legacy/protobuf/TIMESTAMPS.md +++ /dev/null @@ -1,13 +0,0 @@ -# Timestamp - -## Storing as `sint64` - -Proto timestamps were originally stored as `uint64` but changed to `int64` to allow for storage of negative -timestamps (i.e. for birthdays before 1970). - -All new timestamps should use the type `sint64` due to its increased efficiency in comparison to `int64`. - -The reason `uint64` types were not converted to `sint64` types is because the two types are not in-place -compatible. - -https://developers.google.com/protocol-buffers/docs/proto3#updating diff --git a/docs-internal/infrastructure/nats/TROUBLESHOOTING.md b/docs-internal/infrastructure/nats/TROUBLESHOOTING.md deleted file mode 100644 index 28c60c41dc..0000000000 --- a/docs-internal/infrastructure/nats/TROUBLESHOOTING.md +++ /dev/null @@ -1,9 +0,0 @@ -# Troubleshooting - -## Checking the health of the cluster manually... - -1. Open shell to NATS node -2. `nix-shell -p natscli` -3. `nats --server=10.0.44.2:4222 --user admin --password password context save default` -4. `nats context select default` -5. `nats server report connections` diff --git a/docs-internal/infrastructure/networking/EDGE_CLUSTER_NETWORKING.md b/docs-internal/infrastructure/networking/EDGE_CLUSTER_NETWORKING.md deleted file mode 100644 index 4000d2f1b8..0000000000 --- a/docs-internal/infrastructure/networking/EDGE_CLUSTER_NETWORKING.md +++ /dev/null @@ -1,22 +0,0 @@ -# Edge Cluster Networking - -## `gg` - -| Port | Type | Protocol | Description | -| ----------- | ------ | --------- | ------------------------------------------------ | -| 80 | Public | TCP | HTTP & WebSocket traffic to game serves. | -| 443 | Public | TCP | HTTPs & secure WebSocket traffic to game serves. | -| 20000-31999 | Public | TCP & UDP | Ingress traffic to game servers. | - -## `job` - -| Port | Type | Protocol | Description | -| ----------- | ------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 20000-25999 | Private | TCP & UDP | Protected ports that game server ports are assigned to to receive traffic from GG. Nomad automatically assigns ports on this port range. | -| 26000-31999 | Public | TCP & UDP | Unprotected port ranges that job servers using host networking can listen on. Traffic does not go through GG and is vulnerable to attacks. Ports in this range are not automatically assigned. | - -## `ats` - -| Port | Type | Protocol | Description | -| ---- | ------- | -------- | ----------- | -| 8080 | Private | TCP | ATS Server. | diff --git a/docs-internal/infrastructure/networking/IPV6.md b/docs-internal/infrastructure/networking/IPV6.md deleted file mode 100644 index 64e09759d1..0000000000 --- a/docs-internal/infrastructure/networking/IPV6.md +++ /dev/null @@ -1,22 +0,0 @@ -# Why we don't support IPv6 - -**TLDR: We haven't had the time to deal with it yet** - -## Ingress - -Ingress IPv6 should be fairly straightforward to implement for Rivet. - -As long as we have an IPv4 address available for our load balancers, we can use IPv6 for all other servers -without issue. - -### Counting unique IPs - -At the moment, we use a simple IP counting system in the matchmaker that works well enough for IPv4. However, -we need to support counting IPv6 by larger IP blocks, since each residential address may have -[18 quintillion IP unique IP addresses](https://www.computerworld.com/article/2729027/comcast-is-first-u-s--isp-to-offer-ipv6-to-home-gateway-users.html#:~:text=In%20a%20somewhat%20controversial%20move,or%2018%2C446%2C744%2C073%2C709%2C551%2C616%20to%20be%20exact.). - -### Traefik rate limiting - -Traefik does not -[natively support IP blocks](https://doc.traefik.io/traefik/middlewares/http/ratelimit/#sourcecriterionipstrategy) -for rate limiting, which we utilize. diff --git a/docs-internal/infrastructure/networking/IP_RANGES.md b/docs-internal/infrastructure/networking/IP_RANGES.md deleted file mode 100644 index a15a56e130..0000000000 --- a/docs-internal/infrastructure/networking/IP_RANGES.md +++ /dev/null @@ -1,16 +0,0 @@ -# IP Ranges - -See uses of `vlan_ip_net` in `packages/common/config/src/config/server/rivet/cluster_provision.rs`. - -## VLAN (Class A) - -Allowed range: - -| Name | Netmask | Subnet count | Node count | -| ----------------------------- | ----------- | ------------ | ---------------- | -| Entire VLAN | 10.0.0.0/8 | ~ | ~ | -| Region | 10.0.0.0/16 | 256 | ~ | -| Supporting services (GG, ATS) | 10.0.0.0/26 | 16 | 64 - 2 | -| Job | 10.0.4.0/16 | ~ | 65536 - 1024 - 2 | - -We can't allocate the network or broadcast address, so we subtract 2 from each node count. diff --git a/docs-internal/infrastructure/nix/LORRI.md b/docs-internal/infrastructure/nix/LORRI.md deleted file mode 100644 index 22d49af172..0000000000 --- a/docs-internal/infrastructure/nix/LORRI.md +++ /dev/null @@ -1,8 +0,0 @@ -# Lorri - -We recommend installing Lorri on the host machine so you don't have to run `nix-shell` every time you enter -the source directory. - -See installation instructions [here](https://github.com/nix-community/lorri#setup-on-other-platforms). - -Once installed, run `dir-env allow` in the project root. diff --git a/docs-internal/infrastructure/nix/README.md b/docs-internal/infrastructure/nix/README.md deleted file mode 100644 index 6430ef37c7..0000000000 --- a/docs-internal/infrastructure/nix/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Nix - -## What is Nix? - -Nix (not to be confused with Unix and Linux) is a reliable build system. Nix provides a really powerful -deterministic build tool & package management system. It enables us to build tools and expose them to -environments without having to install them on the whole system. It helps ensure that all developers are -running the same versions of the software we use across all platforms. - -## What do we use Nix for? - -**Development environment** - -All commands relating to Rivet need to be ran in a Nix shell. When you run `nix-shell`, the `shell.nix` file -will create a new shell with all of the required packages in `$PATH` and add any extra environment variables -required to interact with Rivet. This way, everyone is running the exact same version of the software with the -exact same environment without having to run a virtual machine to develop with Rivet. - -**Services** - -Nix is used to build dependencies in production instead of using apt or another system package manager to -install them. - -Because Nix supports aggressive caching, we can use the same Nix configs to download cached prebuilt binaries. diff --git a/docs-internal/infrastructure/pegboard/FDB.md b/docs-internal/infrastructure/pegboard/FDB.md deleted file mode 100644 index 8dde56fe8f..0000000000 --- a/docs-internal/infrastructure/pegboard/FDB.md +++ /dev/null @@ -1,24 +0,0 @@ -# Design - -- txns cannot have more than 10MB of data transferred, should be below 1MB - - limit total txn size to 1MB -- txns cannot run for more than 5 seconds (shouldnt be an issue) -- keys cannot be larger than 10KB, but should be below 1KB -- values cannot be larger than 100KB, but should be chunked at 10KB - - use subspace for each key and chunk data - - use get_ranges_key_values to retrieve -- 1GiB max size using get_estimated_range_size_bytes (check before puts) - -## Schema - -``` -structure created - -dir pegboard before actor start - partition {actor_id} before actor start - dir kv before actor start - subspace {key} at start of each put txn - key metadata during put txn - subspace data during put txn - key {idx} during put txn -``` diff --git a/docs-internal/infrastructure/pegboard/ISOLATE_RUNNER.md b/docs-internal/infrastructure/pegboard/ISOLATE_RUNNER.md deleted file mode 100644 index baf51a6fa3..0000000000 --- a/docs-internal/infrastructure/pegboard/ISOLATE_RUNNER.md +++ /dev/null @@ -1,19 +0,0 @@ -# Error handling - -There are several layers of error handling in the isolate runner. Going from the isolate runtime to the main -thread: - -1. Js runtime errors are caught in various places in `run_inner` in `src/isolate.rs`. These are written to the - stderr log stream and visible to users on the dashboard. No error is thrown from the function. -2. Errors besides js runtime errors are thrown by `run_inner` and caught by `run`. An error line is written to - the stderr log stream stating that a fatal error has occurred. An error code of 1 is returned by the `run` - function and no error is thrown by `run`. -3. If any error is thrown by the `run` function (likely during setup or cleanup), it is caught by the tokio - task (in `src/main.rs`) which is watching the thread where the `run` function is running from. Upon any - error, it logs the error and sends a message to the `fatal_tx` channel. -4. The `main` function in `src/main.rs` is a `tokio::select!` on the WS retry loop and `fatal_tx`. If any - message is received on `fatal_tx`, an error code of 1 is written and the program throws "Fatal error". -5. Besides messages from `fatal_tx`, the main function can fail during setup (redirecting logs, reading - config, writing pid, etc) or from fatal errors from the WS connection. This includes bad packets or failed - socket sends. It is intended to fail for these cases, but should automatically handle retryable errors like - the socket closing. diff --git a/docs-internal/infrastructure/pegboard/TROUBLESHOOTING.md b/docs-internal/infrastructure/pegboard/TROUBLESHOOTING.md deleted file mode 100644 index ddf2d44f77..0000000000 --- a/docs-internal/infrastructure/pegboard/TROUBLESHOOTING.md +++ /dev/null @@ -1,51 +0,0 @@ -# Troubleshooting - -## Where are pegboard-manager logs? - -```bash -cat /var/lib/rivet-client/logs -``` - -## Where are rivet-isolate-v8-runner logs? - -```bash -cat /var/lib/rivet-client/runner/logs -``` - -## Why don't my runner logs exist? - -If there are no logs at `/var/lib/rivet-client/runner/logs`, the runner binary likely failed to spawn. - -Common causes: - -- The path to the binary is incorrect -- Error loading libraries -- The binary is not set as executable -- The binary is for the wrong architecture - -Trying to manually find and run the binary usually resolves these issues. - -## `fdb ping missed` - -The `rivet-client` container in `docker/dev-full/docker-compose` has the `fdbcli` CLI installed. - -Check that the cluster can be connected to with: - -```bash -fdbcli -C /var/lib/rivet-client/fdb.cluster --exec status -``` - -For further troupbleshooting, see [FoundationDB troubleshooting](../fdb/TROUBLESHOOTING.md). - -## Getting logs of crashed client in Docker - -If the container crashes, the logs have to be extracted from the volume. - -If log redirection is enabld (you'll see the log `Redirecting all logs to /var/lib/rivet-client/log`), the logs have to be extracted from the volume since the container is down. - -For example, to read the log from the volume `dev-full_client-data`, run this: - -```bash -docker run --rm -it -v dev-full_client-data:/var/lib/rivet-client busybox cat /var/lib/rivet-client/log -``` - diff --git a/docs-internal/infrastructure/rust/TROUBLESHOOTING.md b/docs-internal/infrastructure/rust/TROUBLESHOOTING.md deleted file mode 100644 index dd3fe40fcf..0000000000 --- a/docs-internal/infrastructure/rust/TROUBLESHOOTING.md +++ /dev/null @@ -1,8 +0,0 @@ -# Troubleshooting - -## Large `target` directories - -``` -cargo install cargo-sweep -(cd svc && cargo sweep --time 1) -``` diff --git a/docs-internal/infrastructure/s3/PRESIGNING.md b/docs-internal/infrastructure/s3/PRESIGNING.md deleted file mode 100644 index 557f18a780..0000000000 --- a/docs-internal/infrastructure/s3/PRESIGNING.md +++ /dev/null @@ -1,22 +0,0 @@ -# Presigning - -## Endpoint types - -See documentation on the endpoint types at `s3_util::EndpointKind`. - -## Presigning requests - -Make sure you understand [presigning S3 requests](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html) before reading this. - -Presigned requests need to be made built `EndpointKind::External` in order to ensure the origin is a public endpoint. - -Sometimes you need to create two separate clients: one with `EndpointKind::Internal` for making requests to S3 and one with `EndpointKind::External` for presigning requests. - -## Edge caching - -Rivet edge clusters can optionally run a pull-through S3 cache to acceelrate requests. See `rivet_config::server::rivet::BuildDeliveryMethod` for how this is configured with Dynamic Servers. - -Requests via the edge cache are automatically authenticated to the S3 origin. Do not use presigned requests with the edge cache. - - - diff --git a/docs-internal/infrastructure/s3/TROUBLESHOOTING.md b/docs-internal/infrastructure/s3/TROUBLESHOOTING.md deleted file mode 100644 index 31076b2660..0000000000 --- a/docs-internal/infrastructure/s3/TROUBLESHOOTING.md +++ /dev/null @@ -1,7 +0,0 @@ -# Troubleshooting - -## `BucketNotEmpty: The bucket you tried to delete is not empty` - -``` -aws s3 rm s3://foo --recursive -``` diff --git a/docs-internal/infrastructure/traffic_server/README.md b/docs-internal/infrastructure/traffic_server/README.md deleted file mode 100644 index 1de5f007d4..0000000000 --- a/docs-internal/infrastructure/traffic_server/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# Apache Traffic Server - -## What is Traffic Server? - -Traffic Server is used as a content caching forward proxy within Rivet. It enables us to small and large -files. Unique to Traffic Server, it allows for streaming files while it's being downloaded. - -## What do we Traffic Server for? - -- CDN assets -- Docker image delivery -- Cost savings on frequently requested S3 assets - -## Can we replace Traefik with Traffic Server? - -While Traffic Server is incredibly powerful, flexible, and fast, it doesn't provide the same level of -configuration that Traefik does. diff --git a/docs-internal/infrastructure/traffic_server/WHY_TRAFFIC_SERVER.md b/docs-internal/infrastructure/traffic_server/WHY_TRAFFIC_SERVER.md deleted file mode 100644 index 749e6ac2fc..0000000000 --- a/docs-internal/infrastructure/traffic_server/WHY_TRAFFIC_SERVER.md +++ /dev/null @@ -1,63 +0,0 @@ -# Why Traffic Server? - -## Motivation - -Rivet needs a caching forward proxy for many internal components. - -## Requirements - -- Self-hostable -- High performance -- Pull-through cache -- Serve cold requests while caching at the same time - - Instead of downloading the file to the cache then serving, effectively doubling the download time - -### Nice to haves - -- Cache hierarchy for sharded hashes - - [Hash based routing](https://developer.hashicorp.com/consul/docs/connect/config-entries/service-resolver#hashpolicies) - can be used if not supported natively - -## Alternatives - -### Varnish - -Varnish - -> TODO - -### Squid - -Squid does not support serving files at the same time as caching them. - -Squid is also notoriously slow. Its architecture -[directly led](https://info.varnish-software.com/blog/varnish-or-squid) to the development of Squid. - -### NGINX Plus caching - -NGINX has a caching module, but you must pay for NGINX Plus to use it. NGINX Plus -[starts at $3,675 per module](http://web.archive.org/web/20230601061826/https://www.nginx.com/pricing/). This -is a non-starter for an open source project and is _far_ too expensive for an early stage startup. - -> TODO - -### S3 global replication - -S3 global replication provides many of the same performance benefits that we get out of Traffic Server. - -However, it requires us to replicate our _entire_ S3 buckets which is incredibly expensive, considering the -amount of Docker images & CDN assets we store. - -The requests going straight to S3 will be very expensive, we'll be billed per request. Traffic Server is -within the same datacenter and costs nothing to request a prewarmed file. - -## Shortcomings - -- Traffic Server often fails in non-obvious ways without logging, you need to know what you're doing before - using it -- While we don't need to Dockerize it at the moment, Traffic Server has a slew of bugs inside of Docker -- Development is sluggish - -## Related links - -- [Hacker News](https://news.ycombinator.com/item?id=10983331) diff --git a/docs-internal/libraries/chirp/ERROR_HANDLING.md b/docs-internal/libraries/chirp/ERROR_HANDLING.md deleted file mode 100644 index 73c50e1e1f..0000000000 --- a/docs-internal/libraries/chirp/ERROR_HANDLING.md +++ /dev/null @@ -1,32 +0,0 @@ -# Error Handling - -## Error registry - -All recoverable errors are configured in [`errors/`](../../../errors). - -See the [frontmatter](https://jekyllrb.com/docs/front-matter/) config at -[`lib/formatted-error/build.rs`](../../../lib/formatted-error/build.rs). - -These get auto-generated to https://rivet.gg/docs. - -## Service types - -### Operations: Throw errors normally - -Throw errors using the macros defined in -[`lib/global-error/src/macros.rs`](../../../lib/global-error/src/macros.rs). - -`err_code!` should be used for any potential user error. This throws errors from the error registry. - -`bail!` and `ensure!` should be used like a safe alternative to the `panic!` and `assert!` macro. - -### Consumers: Do or die - -Consumers will be retried until they succeed without an error. Therefore, errors should only be returned if -retrying at a later date will work. - -If an error does need to be handled explicitly by another service, publish a separate message for dispatching -error events (i.e. a consumer of `msg-yak-shake` will produce on error `msg-yak-shave-fail`). - -It's common for consumers to have a separate validation service, e.g. `game-version-create` has a separate -`game-version-validate` service. diff --git a/docs-internal/libraries/chirp/GLOSSARY.md b/docs-internal/libraries/chirp/GLOSSARY.md deleted file mode 100644 index 507640acd6..0000000000 --- a/docs-internal/libraries/chirp/GLOSSARY.md +++ /dev/null @@ -1,31 +0,0 @@ -# Glossary - -## Chirp - -- service: An individual process/container that does something -- chirp client: A lightweight client to interface with Chirp services. Usually used from a _context_. See - `chirp_client::ChirpClient`. -- context: Contexts can represent workers (see `chirp_worker::Message`), operations (see - `rivet_operation::Operation`), or tests (see `chirp_worker::TestCtx`). See `rivet_operation::OperationCtx` - for the core functionality. -- worker: A chunk of code that can process inputs from a stream of messsages/requests. These can be consumers - or rpc endpoints (not currently used). There are usually multiple workers in a single service using a - _worker group_. See `chirp_worker::Manager`. -- worker group: Runs multiple _workers_ in parallel in one process. -- consumer: A type of worker that consumes a stream of messages and has no response. Used for mutating code - that _needs_ to succeed. Requests will be retried until succeeds. -- operation: Ephemeral requests. Used for non-mutating, ephemeral code. Represented as individual Rust - libraries. See `rivet_operation::Operation`. - -### Consumers - -- consumer: a worker that reads messages from a durable stream; these are intended for requests that mutate - state -- message: a event that gets published to a stream and to the pubsub broker -- topic: synonymous with the name of the message; used to define the keys for publishing message events and - storage keys -- parameters: variable data associated with a topic for a given message -- subject: a specific topic & parameter combination (including wildcards), these are used for listening for - events over the pubsub server -- (durable) stream: the data structure (stored in Redis at the moment) used by consumer workers to read and - ack messages reliably diff --git a/docs-internal/libraries/chirp/README.md b/docs-internal/libraries/chirp/README.md deleted file mode 100644 index b3da33a9f0..0000000000 --- a/docs-internal/libraries/chirp/README.md +++ /dev/null @@ -1,208 +0,0 @@ -# Chirp - -> This document is outdated. Please see new best practices uses workflows. - -## What is Chirp? - -Chirp is the system used to communicate between Rivet services. It's built on top of NATS and Redis Streams. -All communication over Chirp is encoded with Protobuf. - -## Service types - -**TLDR** - -- Operations don't mutate databases and can fail. Think of them similar HTTP `GET` requests. -- Workers make changes to databases and retry upon failure. Think of them similar to HTTP - `POST`/`PUT`/`DELETE` requests. - -### Operations - -_Often referred to as `ops`._ - -Operations are the most common type of service in Rivet. - -Operations are used for requests that don't have permanent side effects (e.g. write to a database, making -destructive API calls). They're commonly used for "getters" that execute database queries. - -**Writing operations** - -1. Create the Protobuf interface under `packages/services/*/types/my_operation.proto` -2. Create a library under `packages/services/*/ops/my-operation` -3. Write the operation body under `src/main.rs` -4. Write tests for the operation under `tests/` - -**Calling operations** - -1. Add a dependency to the operation in the service's `Cargo.toml` -2. Call the operation using - ```rust - op!([ctx] my_operation {}).await? - ``` - -**Operations as libraries** - -Rivet is designed around the philosophy of "build libraries, not microservices." - -Each operation is an independent Rust micro-library that depends on other operations as libraries. When you -see `op!` used in the code, it's calling a plain old function under the hood. - -This provides the benefits of explicit isolation & testability of each operation without creating complicated -& wasteful systems for microservices. - -**Error handling** - -Operations can return errors which will be propagated up the call stack. These get converted in to HTTP errors -if originating from an API request. - -See the [error handling guide](/docs/chirp/ERROR_HANDLING.md) for more details. - -### Workers - -Workers are used for two main use cases: - -- Performing operations that have permanent side effects (e.g. writing to a database, making destructive API - calls) -- Consuming & responding to events (e.g. executing code when a user follows another user) - -**Writing workers** - -You'll usually need to create a new message for this worker. Do this first. - -1. Create a worker under `packages/services/*/worker/src/workers/my_worker.rs` -2. Register the worker under `packages/services/*/worker/src/main.rs` - -**Messages** - -Workers are triggered by (or in other words, "consume") messages through an event-based architecture. - -Most workflows inside of Rivet are performed using a -[choreography](https://solace.com/blog/microservices-choreography-vs-orchestration/). - -This has many benefits, among which are: - -- **Interoperability & extensibility** Workers can hook in to events from other parts of the code to add - additional functionality, without modifying other services. For example: - - The Rivet matchmaker is built on top of the abstract job event system without the job package knowing - anything about the matchmaker. - - The Rivet party system hooks in to the matchmaker event lifecycle to provide extra functionality without - modifying the matchmaker at all. -- **Resilience** A lot of things can cause services to fail, like database failures, buggy deploys, and - unexpected panics. Choreographed systems can recover from failures because they are stateless. As opposed to - orchestration with a master server, which can crash and cause systems to fail. -- **Real-time by default** Since every step of a process is triggered by an event, systems are able to display - real time results easily by hooking in to events from API services. -- **Simplicity** Event-based architectures has purely functional consumers with a clear input, output, and - explicit list of messages it can publish. This makes it easy to determine what a service can do and how it - can fail. - -**Queuing** - -Workers are processed in a queue. This makes them suitable for expensive and long-lasting operations. - -**Error handling** - -Errors thrown by workers do not propagate back to whichever service created the message. If a worker throws an -error, then the worker will be retried with exponential back off until it succeeds. - -If you want to be able to catch erroneous behavior from a worker, you need to create an error message type for -the worker (e.g. `packages/services/team/types/msg/create-fail.proto`) and explicitly publish said message upon -erroneous behavior. - -> The reason the term "erroneous behavior" is used instead of just "error" is because when workers error -> "normally", they back off and then retry as noted above. Erroneous behavior is anything that doesn't cause -> the worker to retry (so technically it succeeds), but sends message back to the service that published the -> initial message and allows it to handle that error itself. - -Internal errors like database errors should not be transmitted back to the initial service, since workers -should retry these types of requests. - -See the [error handling guide](/docs/chirp/ERROR_HANDLING.md) for more details. - -In code, this is what a worker with error message pattern might look like: - -- **Initiator** (some other service) - - ```rust - let create_res = msg!([ctx] team::msg::create(team_id) -> Result { - // ... message body - }) - .await?; - match create_res { - Ok(complete_msg) => { - // No error - } - Err(fail_msg) => { - let code = team::msg::create_fail::ErrorCode::from_i32(fail_msg.error_code); - - // Handle error - } - }; - ``` - - or - - ```rust - let complete_res = msg!([ctx] team::msg::create(team_id) -> Result { - // ... message body - }) - .await??; // Note the double `?` - ``` - -- **Worker** - - ```rust - if fail_condition { - msg!([ctx] team::msg::create_fail(team_id) { - error_code: team::msg::create_fail::ErrorCode::ValidationFailed as i32, - }) - .await?; - - // Note here that the worker itself does not fail, it simply sends back a fail message upon erroneous behavior. - return Ok(()); - } else { - msg!([ctx] team::msg::create_complete(team_id) { - // ... message body - }) - .await?; - } - ``` - -**Completion messages** - -It's a common pattern to publish a separate completion message when a worker finishes. - -For example, the `user-create` worker publishes the `msg-user-create-complete` message once complete. API -servers consume this message to know when to return a `200 OK` from the request. - -### Messages - -Messages are a used to represent events or to trigger workers. - -**Publishing messages** - -Messages can be published using the `msg!` macro. - -Messages are encode to Protobuf blobs that get written to both Redis Streams and NATS. - -**Subscribing to messages** - -Services can subscribe to messages by using the `subscribe!` macro. - -This subscribes to the NATS topic to receive the message in realtime. - -To publish a message and subscribe at the same time, the `msg!` macro has various syntaxes to make this -cleaner. See `lib/chirp/client/src/macros.rs` for more info. - -**Workers for consuming messages** - -Workers can be created to consume messages. For example, a `user-create` worker can be created to consume the -`msg-user-create` and the publish the `msg-user-create-complete` message. - -## Service sizes - -Services are designed to be as small as possible. - -Refrain from creating monolithic services that do everything with a complicated request. - -This helps encourage thorough unit tests, isolation & reproducibility of errors, and makes services easier to -comprehend. diff --git a/docs-internal/libraries/workflow/DESIGN.md b/docs-internal/libraries/workflow/DESIGN.md deleted file mode 100644 index cf4c868814..0000000000 --- a/docs-internal/libraries/workflow/DESIGN.md +++ /dev/null @@ -1,5 +0,0 @@ -# Design - -## Hierarchy - -TODO diff --git a/docs-internal/libraries/workflow/ERRORS.md b/docs-internal/libraries/workflow/ERRORS.md deleted file mode 100644 index f7b26b73cb..0000000000 --- a/docs-internal/libraries/workflow/ERRORS.md +++ /dev/null @@ -1,70 +0,0 @@ -# Errors - -## Retries - -Only errors from inside of activities will be retried. Errors thrown in the workflow body will not be retried -because they will never succeed (the state is consistent up the point of error). - -## Workflow errors - -Sub workflow errors cannot be caught because it's up to the workflow to handle its own errors gracefully. - -We return OK responses from workflows for failure cases that we will explicitly handle (e.g. linode server -provision cleaning itself up). See -[Errors that are meant to be propagated up](#errors-that-are-meant-to-be-propagated-up). - -## Propagation - -There are 3 classes of errors in workflows: - -1. Errors that can't be retried -2. Errors that can be retried -3. Errors that are meant to be propagated up - -### Errors that can't be retried - -Certain errors cannot be retried by the workflow system. These are usually problems with the internal -mechanisms of the workflow system itself. - -### Errors that can be retried - -All user errors thrown in an activity will cause a workflow retry. While this is good for errors meant to be -retried, it causes unnecessary retries for errors that you know can't be recovered from (like assertions). We -don't currently have a way to mitigate this besides propagating the errors manually (see below) or letting the -useless retries happen. - -### Errors that are meant to be propagated up - -To propagate an error, you must manually serialize it in the activity/workflow output. The workflow itself -will succeed, but the output data will have the error you want to propagate up. - -You can use nested `Result`'s for this: - -```rust -#[derive(...)] -struct MyActivityInput { } - -type MyActivityOutput = Result; - -#[derive(...)] -struct MyActivityOutputOk { - foo: String, -} - -#[derive(...)] -struct MyActivityOutputErr { - bar: u32, -} - -fn activity(input: MyActivityInput) -> GlobalResult { - if ... { - return Ok(Err(MyActivityOutputErr { - bar: 404, - })); - } - - Ok(Ok(MyActivityOutputOk { - foo: "all good".to_string(), - })) -} -``` diff --git a/docs-internal/libraries/workflow/GLOSSARY.md b/docs-internal/libraries/workflow/GLOSSARY.md deleted file mode 100644 index dcc7e51d0a..0000000000 --- a/docs-internal/libraries/workflow/GLOSSARY.md +++ /dev/null @@ -1,132 +0,0 @@ -# Glossary - -## Worker - -A process that queries for pending workflows with a specific filter. Filter is based on which workflows are -registered in the given worker's registry. The queried workflows are run on the same machine as the worker but -given their own thread. - -## Registry - -A collection of registered workflows. This is solely used for the worker to fetch workflows from the database. - -## Workflow - -A series of fallible executions of code (also known as activities), signal listeners, signal transmitters, or -sub workflow triggers. - -Workflows can be though of as an outline or a list of tasks. The code defining a workflow only specifies what -items should be ran; There is no complex logic (e.g. database queries) running within the top level of the -workflow. - -Upon an activity failure, workflow code can be reran without duplicate side effects because activities are -cached and re-read after they succeed. - -## Activity - -A block of code that can fail. This cannot trigger other workflows or activities, but it can call operations. -Activities are retried by workflows when they fail or replayed when they succeed but a later part of the -workflow fails. - -When choosing between a workflow and an activity: - -- Choose a workflow when there are multiple steps that need to be individually retried upon failure. -- Choose an activity when there is only one chunk of retryable code that needs to be executed. - -## Operation - -Effectively a native rust function. Can fail or not fail. Used for widely used operations like fetching a -user. Operations cannot be called from workflows. - -Examples include: - -- most `get` operations (`user-get`) -- any complex logic you'd want in it's own function (fetching some http data and parsing it) - -Operations are not required; all of their functionality can be put into an activity instead. - -## Tags - -Tags are JSON blobs associated with either workflows or signals. Tags are not meant to be very abstract; i.e. -they should be unique. - -## Signal - -A payload sent to a specific workflow from anywhere else in the codebase. The workflow must be listening for -this signal for it to be picked up, otherwise it will stay in the database indefinitely until consumed by a -workflow. Signals do not have a response; another signal must be sent back from the workflow and listened to -by the sender. - -### Differences between message - -Signals are like messages that can only be consumed by workflows and can only be consumed once. - -## Tagged Signal - -Same as a signal except it is sent with a JSON blob as its "tags" instead of to a specific workflow. Any -workflow with tags that are a superset of the signals tags will consume the signal. Note that tagged signals -are consumed on a first-come-first-serve basis, meaning if there are two workflows that both have a superset -of the signal's tags, only one will receive the signal. - -See [the signals document](./SIGNALS.md). - -## Join Signal - -A "one of" for signal listening. Allows for listening to multiple signals at once and receiving the first one -that gets sent. - -## Message - -A payload that can be sent out of a workflow. Includes a JSON blob for tags which can be subscribed to with a -subscription. - -### Differences between signal - -Messages are like signals that can be only consumed by non workflows and can be consumed by multiple -listeners. - -## Subscription - -An entity that waits for messages with the same (not a superset/subset) tags as itself. Upon receiving a -message, the message will be returned and the developer can choose to continue to listen for more messages. - -## Tail - -Reads the last message without waiting. If none exists (all previous messages expired), `None` is returned. - -## Tail w/ Anchor - -Reads the earliest message after the given anchor timestamp or waits for one to be published if none exist. - -## Workflow Event - -An action that gets executed in a workflow. An event can be a: - -- Activity -- Received signal -- Dispatched sub-workflow - -Events store the output from activities and are used to ensure activities are ran only once. - -## Workflow Event History - -List of events that have executed in this workflow. These are used in replays to verify that the workflow has -not changed to an invalid state. - -## Workflow Replay - -After the first run of a workflow, subsequent runs will replay the activities and compare against the event -history. If an activity has already been ran successfully, the activity will not actually run any code and -instead use the output from the previous run. - -## Workflow Wake Condition - -If a workflow is not currently running an activity, wake conditions define when the workflow should be ran -again. - -The available conditions are: - -- **Immediately** Run immediately by the first available node -- **Deadline** Run at a given timestamp. -- **Signal** Run once any one of the listed signals is received. -- **Sub workflow** Run once the given sub workflow is completed. diff --git a/docs-internal/libraries/workflow/GOTCHAS.md b/docs-internal/libraries/workflow/GOTCHAS.md deleted file mode 100644 index 694150de3b..0000000000 --- a/docs-internal/libraries/workflow/GOTCHAS.md +++ /dev/null @@ -1,226 +0,0 @@ -# Gotchas - -## Timestamps - -Use timestamps with care when passing them between activity inputs/outputs. Because activity inputs need to be -consistent for replays, use `util::timestamp::now()` only within activities and not workflow bodies. - -If you need a timestamp in a workflow body, use `ctx.create_ts()` for the creation of the workflow. Using -`ctx.ts()` is also inconsistent because it marks the start of the current workflow run (which is different -between replays). - -If you need a consistent current timestamp, create a new activity that just returns `util::timestamp::now()`. -This will be the current timestamp on the first execution of the activity and won't change on replay. - -> **When an activity's input doesn't produce the same hash as the first time it was executed (i.e. its input -> changed), the entire workflow will error with "History Diverged" and will not restart.** - -## Randomly generated content - -Randomly generated content like UUIDs should be placed in activities for consistent history. - -## Stale data - -When fetching data for use in a workflow, you will most often put it in an activity for retryability. However, -depending on how much later the data from the activity is used, it may become stale. Make sure to add another -activity where needed when you need more up-to-date info. - -## Spawning a thread - -You should not use `tokio::spawn` to execute workflow code. Instead, dispatch a new workflow and await it for -its output. - -## Consistency with concurrency - -When you need to run multiple workflow events (like activities or signals) in parallel, be careful that you -ensure the state of the context is consistent between replays. - -Take this example trying to concurrently run multiple activities: - -```rust -let iter = actions.into_iter().map(|action| { - let ctx = ctx.clone(); - - async move { - ctx.activity(MyActivityInput { - action, - }).await?; - } - .boxed() -}); - -futures_util::stream::iter(iter) - .buffer_unordered(16) - .try_collect::>() - .await?; -``` - -This will error because of the `ctx.clone()`; each activity has the same internal location because none of the -ctx's know about each other\*. - -Instead, you can increment the location preemptively with `ctx.step()`: - -```rust -let iter = actions.into_iter().map(|action| { - let mut ctx = ctx.step(); - - async move { - ctx.activity(MyActivityInput { - action, - }).await?; - } - .boxed() -}); - -futures_util::stream::iter(iter) - .buffer_unordered(16) - .try_collect::>() - .await?; -``` - -If you plan on running more than one workflow step in each future, use a `closure` stub. - -Note that the first example would also work with a `closure`, but its a bit overkill as it creates a new layer -in the internal location. - -> **\*** Even if they did know about each other via atomics, there is no guarantee of consistency from -> `buffer_unordered`. Preemptively incrementing the location ensures consistency regardless of the order or -> completion time of the futures. - -## Hashmaps in activity inputs/outputs - -`std::collections::HashMap` does not implement `Hash`. To get around this, use `util::serde::HashableMap`: - -```rust -use util::serde::AsHashableExt; -ctx - .activity(MyActivityInput { - map: input.map.as_hashable(), - }) - .await?; -``` - -## Nested options with serde - -Nested options do not serialize/deserialize consistently with serde. - -```rust -Some(Some(1234)) -> "1234" -> Some(Some(1234)) -Some(None) -> "null" -> None -None -> "null" -> None -``` - -Be careful when writing your struct definitions. - -## Force waking a sleeping workflow - -When force waking a sleeping workflow by setting `wake_immediate = true`, know that if the workflow is -currently on a `sleep` step it will go back to sleep if it has not reached its `wake_deadline` yet. For all -other steps, the workflow will continue normally (usually just go back to sleep). - -## Long-lived tasks in `ctx.join` - -When executing multiple long-lived activities in a `ctx.join` call using a tuple, remember that internally it -uses `tokio::join!` and not `tokio::try_join`. This means it will wait until all items finish and does not -short circuit when an `Err` is returned from any branch. - -So if you have an activity that errors immediately and another that takes a while to finish, the `ctx.join` -call will wait until the long task is complete (or errors) before returning. - -## Adding a new sub workflow or closure (branching steps) to an existing workflow - -Be careful that your correctly set the version of new branching steps (sub workflows, closures) so as to not -corrupt the history state. - -Branching steps are unique in that it is possible to corrupt the workflow if you incorrectly set their version -when patching a workflow. For all other step types, the workflow engine will error before any changes to the -history are made. - -**Example** - -```rust -fn my_workflow() { - ctx.activity(Foo); - - ctx.workflow(OtherWorkflow).run(); - - ctx.activity(Lorem); -} - -fn other_workflow() { - ctx.activity(Bar); - ctx.activity(Baz); -} -``` - -**After patching** - -```rust -fn my_workflow() { - ctx.activity(Foo); - - // Forgot to update version to 2 - ctx.workflow(OtherWorkflow2).run(); - ctx.workflow(OtherWorkflow).run(); - - ctx.activity(Lorem); -} - -fn other_workflow() { - ctx.activity(Bar); - ctx.activity(Baz); -} - -fn other_workflow2() { - ctx.v(2).activity(UpdatedBar); - // No baz -} -``` - -The workflow engine does not know the difference between one branch or another. When running `OtherWorkflow2`, -it will enter a branched context which it assumes is the same as the `OtherWorkflow` branch it ran previously. -It will proceed to add `UpdatedBar` as a patch, and then error after it sees that `Bar` and `Baz` no longer -exist in the branch. - -This means the history is now corrupt, as `UpdatedBar` was inserted before an error was thrown. - -**Correct Code** - -```rust -fn my_workflow() { - ctx.activity(Foo); - - ctx.v(2).workflow(OtherWorkflow2).run(); - ctx.workflow(OtherWorkflow).run(); - - ctx.activity(Lorem); -} - -fn other_workflow() { - ctx.activity(Bar); - ctx.activity(Baz); -} - -fn other_workflow2() { - ctx.v(2).activity(UpdatedBar); - // No baz -} -``` - -> Closures and sub workflows function in the same way. They create a new branch in history. - -## Hashes for single-variant enum values - -Rust does not hash the enum discriminant for single-variant enums. This means when you add another variant in -the future, the hash of the existing variant will change. - -This can be fixed with a custom `Hash` impl when you only have 1 variant: - -```rust -impl Hash for ENUM { - fn hash(&self, state: &mut H) { - std::mem::discriminant(self).hash(state); - // ... Hash enum fields, if any - } -} -``` diff --git a/docs-internal/libraries/workflow/LOOPS.md b/docs-internal/libraries/workflow/LOOPS.md deleted file mode 100644 index 3291944630..0000000000 --- a/docs-internal/libraries/workflow/LOOPS.md +++ /dev/null @@ -1,13 +0,0 @@ -# Loops - -TODO - -## Differences between "Continue As New" - -https://docs.temporal.io/develop/go/continue-as-new - -Continue As New effectively wipes the entire history of the workflow, allowing you to start from scratch when -needed. - -With loops, only the history of previous completed iterations of the loop is forgotten. This is because it is -assumed there are no side effects from the loop, meaning previous iterations have no effect on the workflow. diff --git a/docs-internal/libraries/workflow/OVERVIEW.md b/docs-internal/libraries/workflow/OVERVIEW.md deleted file mode 100644 index e363d8f791..0000000000 --- a/docs-internal/libraries/workflow/OVERVIEW.md +++ /dev/null @@ -1,64 +0,0 @@ -# Overview - -Workflows are designed to provide highly durable code executions for distributed systems. The main goal is to allow for writing easy to understand multi-step programs with effective error handling, retryability, and a rigid state. - -## Goals - -**Primary** - -- Performance -- Quick iteration speed -- Architectural simplicity (only depends on CockroachDB) - -**Secondary** - -- Easy to operate, managable via simple SQL queries -- Easier to write, understand, and maintain than event-driven architectures -- Rust-native - - Run in-process and as part of the binary to simplify architecture - - Leverage traits to reduce copies and needless ser/de - - ## Use native serde instead of Protobuf for simplicity (**this comes at the cost of verifiable backwards compatibility with protobuf**) - -## Use cases - -- Billing cron jobs with batch -- Creating servers -- Email loops -- Creating dynamic servers -- Automating Cloudflare APIs (Cloudflare workers, DNS, issuing SSL certs) - -## Relation to existing Chirp primitives - -### Messages - -Workflows replace the use case of messages for durable execution, which is almost all uses of messages. - -The biggest pain point with messages is the lack of a rigid state. Message executions always match the following outline: - -1. Read whatever data is required -2. Perform some action(s) -3. Update data as needed -4. Finish (possibly publish more messages) OR upon failure, start all over at #1 - -The issue with this is that messages do not have any knowledge of messages that came before them, their own previous failed executions, or even other messages of the same system executing in parallel. Without thorough manually written sync checks and consistency validations (which are verbose and hard to follow), this type of execution often results in an overall broken state of whatever system the message is acting on (i.e. matchmaking, server provisioning). - -**Once a broken state is reached, the retry system for messages _practically never_ successfully retries the message.** - -### Cross-package hooks - -We currently use messages for hooking in to events from other workflows so we don't have to bake in support directly. - -This is potentially error prone since it makes control flow more opaque. - -We will use sub workflows instead. - -## Post-workflow message uses - -Messages should still be used, but much less frequently. They're helpful for: - -- Real-time Data Processing -- Complex Event Processing (CEP) -- Data Transformation and Enrichment -- Continuous Data Integration -- Real-time Monitoring and Alerting -- High-throughput, Low-latency Processing diff --git a/docs-internal/libraries/workflow/SIGNALS_AND_MESSAGES.md b/docs-internal/libraries/workflow/SIGNALS_AND_MESSAGES.md deleted file mode 100644 index 49eb2ecbf8..0000000000 --- a/docs-internal/libraries/workflow/SIGNALS_AND_MESSAGES.md +++ /dev/null @@ -1,29 +0,0 @@ -# Signals - -## Tagged signals - -Tagged signals are consumed on a first-come-first-serve basis because a single signal being consumed by more -than one workflow is not a supported design pattern. To work around this, consume the signal by a workflow -then publish multiple signals from that workflow. - -# Choosing Between Signals and Messages - -> **Note**: non-workflow ecosystem is API layer, standalone, operations, old workers - -## Signal - -- Sending data from the non-workflow ecosystem to the workflow ecosystem -- Sending data from the workflow ecosystem to somewhere else in the workflow ecosystem - -## Message - -- Sending data from the workflow ecosystem to the non-workflow ecosystem - -## Both Signals and Messages - -Sometimes you may need to listen for a particular event in the workflow system and the non-workflow ecosystem. -In this case you can publish both a signal and a message (you can derive `signal` and `message` on the same -struct to make this easier). Just remember: signals can only be consumed once. - -Both messages and signals are meant to be payloads with a specific recipient. They are not meant to be -published without an intended target (i.e. any listener can consume). diff --git a/docs-internal/processes/GITHUB_ACTIONS.md b/docs-internal/processes/GITHUB_ACTIONS.md deleted file mode 100644 index 42b8c85a6d..0000000000 --- a/docs-internal/processes/GITHUB_ACTIONS.md +++ /dev/null @@ -1,22 +0,0 @@ -# GitHub Actions - -## When to use self hosted vs managed runners - -**Managed runners** - -Managed runners are good for running bursts of jobs in parallel, quickly. - -Use these for low-CPU intensive jobs, like formatting, linting, etc. Using -these for resource-hungry jobs will make those jobs take a long time and cost a -lot of money. - -**Self-hosted Runners** - -Self-hosted runners are good for running hardware intensive jobs quickly. -However, they have a fixed number of nodes that can run one job at a time each, -so we want to (a) always target 100% resource usage and (b) maintain as few of -these as possible in order to keep them cheap. - -Use these for CPU- & memory-intensive jobs. Using these for low-CPU intensive -jobs will cause jobs to queue up and take a long time to complete. - diff --git a/docs-internal/processes/VERSIONING.md b/docs-internal/processes/VERSIONING.md deleted file mode 100644 index 116a9f9ade..0000000000 --- a/docs-internal/processes/VERSIONING.md +++ /dev/null @@ -1,46 +0,0 @@ -# Versioning - -Rivet uses [CalVer](https://calver.org/) for versioning. - -## What is CalVer? - -CalVer (calendar versioning) is a [SemVer](https://semver.org/)-compatible versioning scheme based on -projects' release cycles. - -A [long list](https://calver.org/users.html) of projects have been successfully using CalVer for a long time. - -## How does it work? - -See the [CalVer versioning scheme](https://calver.org/#scheme). - -Rivet specifically uses: - -``` -YY.MINOR.MICRO -``` - -## Motivations for using CalVer - -- We don't ship breaking changes, which makes SemVer less effective. Any significant changes we have _must_ - have graceful migrations that run automatically. -- We ship on a rolling basis, which makes including the year & release cycle more informational. -- Maintain compatibility with SemVer for releasing patches for older versions. -- Versions like `23.2.1` are more intuitive than a verbose SemVer version like `1.46.1`. - -## Why not date by month/week? - -Many projects date their releases by month or week. (e.g. Ubuntu & NixOS use `YYYY.0M`, Tesla uses -`YYYY.MM.MICRO`) - -**Release schedule** - -Internally, Rivet does not have a structured release cycle (yet). We encourage shipping code as fast as -possible instead of creating a rigid schedule that all projects have to synchronize to. This lets us deliver -features to users faster (often within 48h) and removes the friction around managing multiple projects. - -As we scale, this will likely change. - -**Minor patches** - -When we patch a security issue, we must patch older minor Rivet versions to stay compatible with SemVer. If we -ship a minor version too frequently (e.g. on a weekly basis), it becomes difficult to patch older versions. diff --git a/docs-internal/services/api-auth/HUB_AUTH.md b/docs-internal/services/api-auth/HUB_AUTH.md deleted file mode 100644 index 6a183f37b5..0000000000 --- a/docs-internal/services/api-auth/HUB_AUTH.md +++ /dev/null @@ -1,17 +0,0 @@ -# Hub Authentication - -There are two important tokens for user authentication in the hub. - -**Refresh token** - -- Expires after 90 days -- Includes a _refresh_ entitlement that includes the user entitlement to generate -- Single-use and will be regenerated upon consumption with a new expiration -- Will update the stored session data every time it is used -- Stored as an `HttpOnly` cookie - -**User token** - -- Expires after 15 minutes -- Includes a _user_ entitlement for the given user -- Generated using the refresh token above diff --git a/docs-internal/services/upload/UPLOADS.md b/docs-internal/services/upload/UPLOADS.md deleted file mode 100644 index 2d1287817e..0000000000 --- a/docs-internal/services/upload/UPLOADS.md +++ /dev/null @@ -1,13 +0,0 @@ -# Uploads - -## Procedure - -1. Call `upload-prepare` -1. Send presigned link to client -1. Client uploads files to that link -1. Call `upload-complete` and save the upload ID somewhere - - Make sure to save the upload ID only once the upload is complete - -## Making files public - -Create a Traefik rule for this. diff --git a/examples/.vscode/settings.json b/examples/.vscode/settings.json deleted file mode 100644 index 7c2b296378..0000000000 --- a/examples/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "editor.defaultFormatter": "biomejs.biome" -} \ No newline at end of file diff --git a/examples/README.md b/examples/README.md deleted file mode 100644 index fb64a6640a..0000000000 --- a/examples/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Examples & Templates - -These are examples & templates for Rivet. - -## Development - -Examples can be deployed to either a local Rivet cluster or a production Rivet cluster. - -If using bleeding edge examples, it's recommended to use `cargo run` to auto-build the Rivet CLI. For example, to deploy the counter example: - -``` -cd examples/javascript/counter -cargo run --bin rivet -- deploy -``` - diff --git a/examples/functions-js/http.ts b/examples/functions-js/http.ts deleted file mode 100644 index 177d7e68f0..0000000000 --- a/examples/functions-js/http.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { ActorContext } from "@rivet-gg/actor-core"; -import { Hono } from "hono"; - -// Setup Hono app -const app = new Hono(); - -app.get("/", (c) => { - return c.text("ok"); -}); - -app.get("/health", (c) => { - return c.text("ok"); -}); - -// Start server -export default { - async start(ctx: ActorContext) { - // Find port - const portEnv = Deno.env.get("PORT_HTTP"); - if (!portEnv) { - throw new Error("missing PORT_HTTP"); - } - const port = Number.parseInt(portEnv); - - // Start server - console.log(`Listening on port ${port}`); - const server = Deno.serve({ port }, app.fetch); - await server.finished; - }, -}; diff --git a/examples/functions-js/package.json b/examples/functions-js/package.json deleted file mode 100644 index bb9ce4299d..0000000000 --- a/examples/functions-js/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "example-functions", - "version": "1.0.0", - "private": true, - "dependencies": { - "@rivet-gg/actor": "^5.1.2", - "hono": "^4.6.17" - } -} diff --git a/examples/functions-js/rivet.json b/examples/functions-js/rivet.json deleted file mode 100644 index f1289d0630..0000000000 --- a/examples/functions-js/rivet.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "functions": { - "simple": { - "script": "http.ts" - } - } -} diff --git a/examples/functions-js/tsconfig.json b/examples/functions-js/tsconfig.json deleted file mode 100644 index afacad332e..0000000000 --- a/examples/functions-js/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "compilerOptions": { - "target": "ESNext", - "module": "ESNext", - "moduleResolution": "bundler", - "types": ["node", "deno"], - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - "noEmit": true, - "isolatedModules": true - }, - "include": ["**/*.ts"] -} diff --git a/examples/functions-rust/Cargo.lock b/examples/functions-rust/Cargo.lock deleted file mode 100644 index 4a48c2a907..0000000000 --- a/examples/functions-rust/Cargo.lock +++ /dev/null @@ -1,1584 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "actix-codec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" -dependencies = [ - "bitflags", - "bytes", - "futures-core", - "futures-sink", - "memchr", - "pin-project-lite", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "actix-http" -version = "3.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa882656b67966045e4152c634051e70346939fced7117d5f0b52146a7c74c9" -dependencies = [ - "actix-codec", - "actix-rt", - "actix-service", - "actix-utils", - "base64", - "bitflags", - "brotli", - "bytes", - "bytestring", - "derive_more", - "encoding_rs", - "flate2", - "foldhash", - "futures-core", - "h2", - "http", - "httparse", - "httpdate", - "itoa", - "language-tags", - "local-channel", - "mime", - "percent-encoding", - "pin-project-lite", - "rand", - "sha1", - "smallvec", - "tokio", - "tokio-util", - "tracing", - "zstd", -] - -[[package]] -name = "actix-macros" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "actix-router" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" -dependencies = [ - "bytestring", - "cfg-if", - "http", - "regex", - "regex-lite", - "serde", - "tracing", -] - -[[package]] -name = "actix-rt" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208" -dependencies = [ - "futures-core", - "tokio", -] - -[[package]] -name = "actix-server" -version = "2.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6398974fd4284f4768af07965701efbbb5fdc0616bff20cade1bb14b77675e24" -dependencies = [ - "actix-rt", - "actix-service", - "actix-utils", - "futures-core", - "futures-util", - "mio", - "socket2", - "tokio", - "tracing", -] - -[[package]] -name = "actix-service" -version = "2.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e46f36bf0e5af44bdc4bdb36fbbd421aa98c79a9bce724e1edeb3894e10dc7f" -dependencies = [ - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "actix-utils" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" -dependencies = [ - "local-waker", - "pin-project-lite", -] - -[[package]] -name = "actix-web" -version = "4.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2e3b15b3dc6c6ed996e4032389e9849d4ab002b1e92fbfe85b5f307d1479b4d" -dependencies = [ - "actix-codec", - "actix-http", - "actix-macros", - "actix-router", - "actix-rt", - "actix-server", - "actix-service", - "actix-utils", - "actix-web-codegen", - "bytes", - "bytestring", - "cfg-if", - "cookie", - "derive_more", - "encoding_rs", - "foldhash", - "futures-core", - "futures-util", - "impl-more", - "itoa", - "language-tags", - "log", - "mime", - "once_cell", - "pin-project-lite", - "regex", - "regex-lite", - "serde", - "serde_json", - "serde_urlencoded", - "smallvec", - "socket2", - "time", - "tracing", - "url", -] - -[[package]] -name = "actix-web-codegen" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f591380e2e68490b5dfaf1dd1aa0ebe78d84ba7067078512b4ea6e4492d622b8" -dependencies = [ - "actix-router", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "alloc-no-stdlib" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" - -[[package]] -name = "alloc-stdlib" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" -dependencies = [ - "alloc-no-stdlib", -] - -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[package]] -name = "backtrace" -version = "0.3.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets", -] - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "bitflags" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "brotli" -version = "7.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli-decompressor" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a334ef7c9e23abf0ce748e8cd309037da93e606ad52eb372e4ce327a0dcfbdfd" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - -[[package]] -name = "bytes" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" - -[[package]] -name = "bytestring" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e465647ae23b2823b0753f50decb2d5a86d2bb2cac04788fafd1f80e45378e5f" -dependencies = [ - "bytes", -] - -[[package]] -name = "cc" -version = "1.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04da6a0d40b948dfc4fa8f5bbf402b0fc1a64a28dbf7d12ffd683550f2c1b63a" -dependencies = [ - "jobserver", - "libc", - "shlex", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cookie" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" -dependencies = [ - "percent-encoding", - "time", - "version_check", -] - -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - -[[package]] -name = "crc32fast" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "deranged" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "derive_more" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" -dependencies = [ - "derive_more-impl", -] - -[[package]] -name = "derive_more-impl" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "unicode-xid", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "encoding_rs" -version = "0.8.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "env_logger" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" -dependencies = [ - "humantime", - "is-terminal", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "flate2" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "functions-rust" -version = "0.1.0" -dependencies = [ - "actix-web", - "env_logger", - "log", -] - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-sink" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" - -[[package]] -name = "futures-task" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" - -[[package]] -name = "futures-util" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" -dependencies = [ - "futures-core", - "futures-task", - "pin-project-lite", - "pin-utils", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasi 0.14.2+wasi-0.2.4", -] - -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" - -[[package]] -name = "hermit-abi" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e" - -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "httparse" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "humantime" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" - -[[package]] -name = "icu_collections" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locid" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" - -[[package]] -name = "icu_normalizer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "utf16_iter", - "utf8_iter", - "write16", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" - -[[package]] -name = "icu_properties" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locid_transform", - "icu_properties_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" - -[[package]] -name = "icu_provider" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_provider_macros", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "idna" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - -[[package]] -name = "impl-more" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2" - -[[package]] -name = "indexmap" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" -dependencies = [ - "equivalent", - "hashbrown", -] - -[[package]] -name = "is-terminal" -version = "0.4.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "itoa" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - -[[package]] -name = "jobserver" -version = "0.1.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" -dependencies = [ - "getrandom", - "libc", -] - -[[package]] -name = "language-tags" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" - -[[package]] -name = "libc" -version = "0.2.172" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" - -[[package]] -name = "litemap" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" - -[[package]] -name = "local-channel" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" -dependencies = [ - "futures-core", - "futures-sink", - "local-waker", -] - -[[package]] -name = "local-waker" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "miniz_oxide" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" -dependencies = [ - "adler2", -] - -[[package]] -name = "mio" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" -dependencies = [ - "libc", - "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets", -] - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "proc-macro2" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" - -[[package]] -name = "rand" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" -dependencies = [ - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -dependencies = [ - "getrandom", -] - -[[package]] -name = "redox_syscall" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" -dependencies = [ - "bitflags", -] - -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-lite" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "serde" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.140" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook-registry" -version = "1.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" -dependencies = [ - "libc", -] - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" - -[[package]] -name = "socket2" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "syn" -version = "2.0.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "synstructure" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "time" -version = "0.3.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" - -[[package]] -name = "time-macros" -version = "0.2.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tinystr" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" -dependencies = [ - "displaydoc", - "zerovec", -] - -[[package]] -name = "tokio" -version = "1.44.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "windows-sys 0.52.0", -] - -[[package]] -name = "tokio-util" -version = "0.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tracing" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" -dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing-core" -version = "0.1.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" -dependencies = [ - "once_cell", -] - -[[package]] -name = "typenum" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" - -[[package]] -name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - -[[package]] -name = "url" -version = "2.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" -dependencies = [ - "wit-bindgen-rt", -] - -[[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "wit-bindgen-rt" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags", -] - -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - -[[package]] -name = "writeable" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" - -[[package]] -name = "yoke" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zerocopy" -version = "0.8.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zerofrom" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zerovec" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zstd" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "7.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" -dependencies = [ - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.15+zstd.1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" -dependencies = [ - "cc", - "pkg-config", -] diff --git a/examples/functions-rust/Cargo.toml b/examples/functions-rust/Cargo.toml deleted file mode 100644 index 32672022a1..0000000000 --- a/examples/functions-rust/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "functions-rust" -version = "0.1.0" -edition = "2021" - -[dependencies] -actix-web = "4.10" -env_logger = "0.10" -log = "0.4" - -# Exclude from parent workspace -[workspace] - diff --git a/examples/functions-rust/Dockerfile b/examples/functions-rust/Dockerfile deleted file mode 100644 index 0c0e846ac7..0000000000 --- a/examples/functions-rust/Dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -FROM rust:1.86-bullseye as builder - -WORKDIR /app -COPY Cargo.toml . -COPY src ./src - -RUN cargo build --release - -FROM debian:bullseye-slim - -WORKDIR /app - -# Create rivet user and set permissions -RUN groupadd -r rivet && useradd -r -g rivet rivet - -# Install necessary dependencies for running the binary -RUN apt-get update && \ - apt-get install -y --no-install-recommends ca-certificates && \ - rm -rf /var/lib/apt/lists/* - -# Copy the built binary from the builder stage -COPY --from=builder /app/target/release/functions-rust /app/functions-rust -RUN chown -R rivet:rivet /app - -# Switch to non-root user -USER rivet - -# Run the binary -CMD ["/app/functions-rust"] diff --git a/examples/functions-rust/rivet.json b/examples/functions-rust/rivet.json deleted file mode 100644 index 84f6350f41..0000000000 --- a/examples/functions-rust/rivet.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "functions": { - "simple": { - "dockerfile": "Dockerfile" - } - } -} diff --git a/examples/functions-rust/src/main.rs b/examples/functions-rust/src/main.rs deleted file mode 100644 index 6b593481ea..0000000000 --- a/examples/functions-rust/src/main.rs +++ /dev/null @@ -1,28 +0,0 @@ -use actix_web::{web, App, HttpResponse, HttpServer, Responder}; -use std::env; - -async fn index() -> impl Responder { - HttpResponse::Ok().body("ok") -} - -async fn health() -> impl Responder { - HttpResponse::Ok().body("ok") -} - -#[actix_web::main] -async fn main() -> std::io::Result<()> { - // Find port - let port_str = env::var("PORT_HTTP").expect("missing PORT_HTTP"); - let port = port_str.parse::().expect("invalid PORT_HTTP"); - - println!("Listening on port {}", port); - - HttpServer::new(|| { - App::new() - .route("/", web::get().to(index)) - .route("/health", web::get().to(health)) - }) - .bind(("0.0.0.0", port))? - .run() - .await -} \ No newline at end of file diff --git a/examples/linear-agent-starter/.gitignore b/examples/linear-agent-starter/.gitignore deleted file mode 100644 index 79b7a1192f..0000000000 --- a/examples/linear-agent-starter/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.actorcore -node_modules \ No newline at end of file diff --git a/examples/linear-agent-starter/README.md b/examples/linear-agent-starter/README.md deleted file mode 100644 index f6d5213a3a..0000000000 --- a/examples/linear-agent-starter/README.md +++ /dev/null @@ -1,106 +0,0 @@ -# Linear Agent Starter - -A starter template for building a Linear agent using [Rivet](https://rivet.gg) and [ActorCore](https://actorcore.org). This example agent helps developers by generating code based on issue descriptions and requirements. - -The agent can: -- Act on issues when assigned to it -- React to comment mentions with 👀 and generate code-focused responses - -This simple example serves as a starting point for building more sophisticated Linear agents. For full documentation on Linear Agents, see the [Linear Agents documentation](https://linear.app/developers/agents). - -## Getting Started - -## TL;DR - -See `src/actors/issue-agent.ts` for the brains of the whole thing. - -### Prerequisites - -- Node.js (v18+) -- Linear account and API access -- Anthropic API key (can be swapped for any [AI SDK provider](https://ai-sdk.dev/docs/foundations/providers-and-models)) -- [ngrok](https://ngrok.com/download) for exposing your local server to the internet - -### Setup and Configuration - -1. Clone the repository and navigate to the example: - ```bash - git clone https://github.com/rivet-gg/rivet.git - cd rivet/examples/linear-agent-starter - ``` - -2. Install dependencies: - ```bash - npm install - ``` -3. Set up ngrok for webhook and OAuth callback handling: - - ```bash - # With a consistent URL (recommended) - ngrok http 5050 --url=YOUR-NGROK-URL - - # Or without a consistent URL - ngrok http 5050 - ``` - -4. Create a Linear OAuth application: - 1. Go to to [Linear's create application page](https://linear.app/settings/api/applications/new) - 2. Enter your _Application name_, _Developer name_, _Developer URL_, _Description_, and _GitHub username_ for your agent - 3. Set _Callback URL_ to `https://YOUR-NGROK-URL/oauth/callback/linear` (replace `YOUR-NGROK-URL` with your actual [ngrok URL](https://ngrok.com/docs/universal-gateway/domains/)) - * This URL is where Linear will redirect after OAuth authorization - 4. Enable webhooks - 5. Set _Webhook URL_ to `https://YOUR-NGROK-URL/webhook/linear` (use the same ngrok URL) - * This URL is where Linear will send events when your agent is mentioned or assigned - 6. Enable _Inbox notifications_ webhook events - 7. Create the application to get your _Client ID_, _Client Secret_, and webhook _Signing secret_ - -

- Linear App Setup -

- -5. Create a `.env.local` file with your credentials: - ``` - LINEAR_OAUTH_CLIENT_ID= - LINEAR_OAUTH_CLIENT_AUTHENTICATION= - LINEAR_OAUTH_REDIRECT_URI=https://YOUR-NGROK-URL/oauth/callback/linear - LINEAR_WEBHOOK_SECRET= - ANTHROPIC_API_KEY= - ``` - - Remember to replace `YOUR-NGROK-URL` with your actual ngrok URL (without the https:// prefix). - -### Running the Development Server - -```bash -npm run dev -``` - -The server will start on port 5050. Visit http://127.0.0.1:5050/connect-linear to add the agent to your workspace. - -### Testing the Agent - -Once the agent is installed in your workspace, create a new issue and assign it to the agent. The agent will generate code for you based on your issue. - -You can mention the agent in comments to iterate on the code. - -## Architecture - -This project uses [ActorCore](https://actorcore.org) to manage stateful actors with a [Hono](https://hono.dev/) HTTP server. - -### Actors - -All actor files are located in the `src/actors/` directory: - -- **Issue Agent** (`src/actors/issue-agent.ts`): Handles Linear issue events and generates responses -- **Linear App User** (`src/actors/linear-app-user.ts`): Manages authentication state for the application -- **OAuth Session** (`src/actors/oauth-session.ts`): Handles OAuth flow state - -### Server Endpoints - -The server implementation is in `src/server/index.ts`: - -- `GET /connect-linear`: Initiates the Linear OAuth flow -- `GET /oauth/callback/linear`: OAuth callback endpoint -- `POST /webhook/linear`: Receives Linear webhook events - -The server handles the OAuth flow, authenticates with Linear, and routes events to the appropriate actors for processing. diff --git a/examples/linear-agent-starter/media/app-setup.png b/examples/linear-agent-starter/media/app-setup.png deleted file mode 100644 index 876ce7178b..0000000000 Binary files a/examples/linear-agent-starter/media/app-setup.png and /dev/null differ diff --git a/examples/linear-agent-starter/package.json b/examples/linear-agent-starter/package.json deleted file mode 100644 index ffe55a4ea1..0000000000 --- a/examples/linear-agent-starter/package.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "linear-agent-starter", - "version": "0.0.0", - "private": true, - "type": "module", - "scripts": { - "dev": "npx tsx --watch src/server/index.ts", - "dev:check-types": "npx tsc --noEmit --watch", - "check-types": "tsc --noEmit", - "test": "vitest run", - "deploy": "npx @actor-core/cli deploy rivet actors/app.ts" - }, - "devDependencies": { - "@actor-core/cli": "0.9.0-rc.1", - "@actor-core/rivet": "0.9.0-rc.1", - "@types/deno": "^2.2.0", - "@types/invariant": "^2", - "@types/node": "^22.13.9", - "actor-core": "0.9.0-rc.1", - "tsx": "^3.12.7", - "typescript": "^5.7.3", - "vitest": "^3.1.1" - }, - "stableVersion": "0.8.0", - "dependencies": { - "@actor-core/nodejs": "0.9.0-rc.1", - "@ai-sdk/anthropic": "^1.2.12", - "@ai-sdk/openai": "^1.3.22", - "@linear/sdk": "^40.0.0", - "ai": "^4.3.16", - "dotenv": "^16.5.0", - "hono": "^4.7.0", - "invariant": "^2.2.4", - "openid-client": "^6.5.0" - } -} diff --git a/examples/linear-agent-starter/src/actors/app.ts b/examples/linear-agent-starter/src/actors/app.ts deleted file mode 100644 index 980e2f91eb..0000000000 --- a/examples/linear-agent-starter/src/actors/app.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { setup } from "actor-core"; -import { createClient } from "actor-core/client"; -import { BASE_PATH, PORT } from "../config"; -import { issueAgent } from "./issue-agent"; -import { linearAppUser } from "./linear-app-user"; -import { oauthSession } from "./oauth-session"; - -export const app = setup({ - actors: { issueAgent, oauthSession, linearAppUser }, - basePath: BASE_PATH, -}); - -export type App = typeof app; - -export const actorClient = createClient( - `http://127.0.0.1:${PORT}${BASE_PATH}`, -); diff --git a/examples/linear-agent-starter/src/actors/issue-agent.ts b/examples/linear-agent-starter/src/actors/issue-agent.ts deleted file mode 100644 index 003c924af6..0000000000 --- a/examples/linear-agent-starter/src/actors/issue-agent.ts +++ /dev/null @@ -1,190 +0,0 @@ -import { anthropic } from "@ai-sdk/anthropic"; -import { LinearClient } from "@linear/sdk"; -import { type ActionContextOf, actor } from "actor-core"; -import { type CoreMessage, generateText } from "ai"; -import type { WebhookComment, WebhookIssue } from "../linear-types"; -import { actorClient } from "./app"; - -interface IssueAgentState { - messages: CoreMessage[]; -} - -export const issueAgent = actor({ - state: { - messages: [], - } as IssueAgentState, - actions: { - issueMention: async (c, appUserId: string, issue: WebhookIssue) => { - // Do nothing - }, - issueEmojiReaction: async ( - c, - appUserId: string, - issue: WebhookIssue, - emoji: string, - ) => { - // Do nothing - }, - issueCommentMention: async ( - c, - appUserId: string, - issue: WebhookIssue, - comment: WebhookComment, - ) => { - c.log.info("mentioned in comment", { - issue: issue.id, - comment: comment.id, - }); - - const linearClient = await buildLinearClient(appUserId); - - c.log.info("acknowledging comment", { - issue: issue.id, - comment: comment.id, - }); - await linearClient.createReaction({ - commentId: comment.id, - emoji: "👀", - }); - - c.log.info("generating response to comment", { - issue: issue.id, - comment: comment.id, - }); - const fetchedComment = await linearClient.comment({ - id: comment.id, - }); - const response = await prompt( - c, - `The user mentioned me in a comment:\n\n\`\`\`\n${comment.body}\n\`\`\``, - ); - await linearClient.createComment({ - issueId: issue.id, - // Must use the top-most comment ID - parentId: fetchedComment.parentId ?? comment.id, - body: response, - }); - }, - issueAssignedToYou: async ( - c, - appUserId: string, - issue: WebhookIssue, - ) => { - c.log.info(`Issue assigned to app: ${issue.title} (${issue.id})`); - const linearClient = await buildLinearClient(appUserId); - - // Set issue as started - c.log.info("finding issue state", { issue: issue.id }); - const fetchedIssue = await linearClient.issue(issue.id); - const state = await fetchedIssue.state; - if ( - state && - state.type !== "started" && - state.type !== "completed" && - state.type !== "canceled" - ) { - const states = await linearClient.workflowStates(); - const startedState = states.nodes.find( - (s) => s.type === "started", - ); - if (startedState) { - c.log.info("updating issue state", { - issue: issue.id, - state: startedState.id, - }); - await fetchedIssue.update({ stateId: startedState.id }); - } else { - c.log.warn("could not find started state"); - } - } - - // Generate response - c.log.info("generating response to issue", { issue: issue.id }); - const response = await prompt( - c, - `I've been assigned to issue: "${issue.title}". The description is:\n\n\`\`\`\n${fetchedIssue.description}\n\`\`\``, - ); - await linearClient.createComment({ - issueId: issue.id, - body: response, - }); - }, - issueCommentReaction: async ( - c, - appUserId: string, - issue: WebhookIssue, - comment: WebhookComment, - emoji: string, - ) => { - // Do nothing - }, - issueUnassignedFromYou: async ( - c, - appUserId: string, - issue: WebhookIssue, - ) => { - const linearClient = await buildLinearClient(appUserId); - - c.log.info("responding to issue unassigned", { issue: issue.id }); - await linearClient.createComment({ - issueId: issue.id, - body: "I've been unassigned from this issue.", - }); - }, - issueNewComment: async ( - c, - appUserId: string, - issue: WebhookIssue, - comment: WebhookComment, - ) => { - // Do nothing - }, - issueStatusChanged: async ( - c, - appUserId: string, - issue: WebhookIssue, - ) => { - // Do nothing - }, - }, -}); - -async function buildLinearClient(appUserId: string): Promise { - const accessToken = await actorClient.linearAppUser - .get(appUserId) - .getAccessToken(); - return new LinearClient({ accessToken }); -} - -const SYSTEM_PROMPT = ` -You are a code generation assistant for Linear. Your job is to: - -1. Read issue descriptions and generate appropriate code solutions -2. Iterate on your code based on comments and feedback -3. Provide brief explanations of your implementation - -When responding: -- Always provide the full requested code -- Do not exclude parts of the code, always include the full code -- Focus on delivering working code that meets requirements -- Keep explanations concise and relevant -- If no language is specified, use TypeScript - -Your goal is to save developers time by providing ready-to-implement solutions. -`; - -async function prompt(c: ActionContextOf, content: string) { - c.log.debug("generating text", { messages: c.state.messages }); - - c.state.messages.push({ role: "user", content }); - - const { text, response } = await generateText({ - model: anthropic("claude-4-opus-20250514"), - system: SYSTEM_PROMPT, - messages: c.state.messages, - }); - - c.state.messages.push(...response.messages); - - return text; -} diff --git a/examples/linear-agent-starter/src/actors/linear-app-user.ts b/examples/linear-agent-starter/src/actors/linear-app-user.ts deleted file mode 100644 index e0d1e2b3ce..0000000000 --- a/examples/linear-agent-starter/src/actors/linear-app-user.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { actor } from "actor-core"; - -interface LinearAppUserState { - accessToken?: string; -} - -export const linearAppUser = actor({ - state: {} as LinearAppUserState, - actions: { - setAccessToken: (c, accessToken: string) => { - c.state.accessToken = accessToken; - }, - getAccessToken: (c) => { - return c.state.accessToken; - }, - }, -}); diff --git a/examples/linear-agent-starter/src/actors/oauth-session.ts b/examples/linear-agent-starter/src/actors/oauth-session.ts deleted file mode 100644 index 3e91ec2b85..0000000000 --- a/examples/linear-agent-starter/src/actors/oauth-session.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { actor } from "actor-core"; - -interface OAuthSessionInput { - oauthState: string; -} - -interface OAuthSessoinState { - oauthState: string; - accessToken?: string; -} - -export interface OAuthExpectedState { - sessionId: string; - nonce: string; -} - -export const oauthSession = actor({ - createState: (c, opts) => - ({ - oauthState: (opts.input as OAuthSessionInput).oauthState, - }) satisfies OAuthSessoinState, - actions: { - getOAuthState: (c) => c.state.oauthState, - }, -}); diff --git a/examples/linear-agent-starter/src/config.ts b/examples/linear-agent-starter/src/config.ts deleted file mode 100644 index 49775913a2..0000000000 --- a/examples/linear-agent-starter/src/config.ts +++ /dev/null @@ -1,28 +0,0 @@ -import * as dotenv from "dotenv"; -dotenv.config({ path: ".env.local" }); - -import invariant from "invariant"; - -// Linear -export const LINEAR_WEBHOOK_SECRET = process.env.LINEAR_WEBHOOK_SECRET!; -invariant(LINEAR_WEBHOOK_SECRET, "missing LINEAR_WEBHOOK_SECRET"); - -export const LINEAR_OAUTH_CLIENT_ID = process.env.LINEAR_OAUTH_CLIENT_ID!; -invariant(LINEAR_OAUTH_CLIENT_ID, "missing LINEAR_OAUTH_CLIENT_ID"); - -export const LINEAR_OAUTH_CLIENT_AUTHENTICATION = - process.env.LINEAR_OAUTH_CLIENT_AUTHENTICATION!; -invariant( - LINEAR_OAUTH_CLIENT_AUTHENTICATION, - "missing LINEAR_OAUTH_CLIENT_AUTHENTICATION", -); - -export const LINEAR_OAUTH_REDIRECT_URI = process.env.LINEAR_OAUTH_REDIRECT_URI!; -invariant(LINEAR_OAUTH_REDIRECT_URI, "missing LINEAR_OAUTH_REDIRECT_URI"); -console.log("Redirect URI:", LINEAR_OAUTH_REDIRECT_URI); - -// Server -export const PORT = process.env.PORT ? Number.parseInt(process.env.PORT) : 5050; - -// ActorCore -export const BASE_PATH = "/actors"; diff --git a/examples/linear-agent-starter/src/linear-types.ts b/examples/linear-agent-starter/src/linear-types.ts deleted file mode 100644 index 92d89eb4f4..0000000000 --- a/examples/linear-agent-starter/src/linear-types.ts +++ /dev/null @@ -1,58 +0,0 @@ -// These types need to be manually defined since @linear/sdk doesn't include types from webhooks - -export interface LinearWebhookEvent { - type: string; - action: string; - createdAt: string; - organizationId: string; - oauthClientId: string; - appUserId: string; - notification: WebhookNotification; - webhookTimestamp: number; - webhookId: string; -} - -export interface WebhookNotification { - id: string; - createdAt: string; - updatedAt: string; - archivedAt: string | null; - type: string; - actorId: string; - externalUserActorId: string | null; - userId: string; - readAt: string | null; - emailedAt: string | null; - snoozedUntilAt: string | null; - unsnoozedAt: string | null; - issueId: string; - issue: WebhookIssue; - commentId?: string; - comment?: WebhookComment; - actor: WebhookActor; - reactionEmoji?: string; -} - -export interface WebhookIssue { - id: string; - title: string; - teamId: string; - team: unknown; - identifier: string; - url: string; -} - -export interface WebhookComment { - id: string; - body: string; - userId: string; - issueId: string; -} - -export interface WebhookActor { - id: string; - name: string; - email: string; - avatarUrl: string; - url: string; -} diff --git a/examples/linear-agent-starter/src/server/index.ts b/examples/linear-agent-starter/src/server/index.ts deleted file mode 100644 index f2d982f56e..0000000000 --- a/examples/linear-agent-starter/src/server/index.ts +++ /dev/null @@ -1,227 +0,0 @@ -import { atob } from "node:buffer"; -import crypto from "node:crypto"; -import { createRouter } from "@actor-core/nodejs"; -import { serve } from "@hono/node-server"; -import { LinearClient } from "@linear/sdk"; -import { Hono } from "hono"; -import * as openidClient from "openid-client"; -import { actorClient, app } from "../actors/app"; -import type { OAuthExpectedState } from "../actors/oauth-session"; -import { - BASE_PATH, - LINEAR_OAUTH_CLIENT_AUTHENTICATION, - LINEAR_OAUTH_CLIENT_ID, - LINEAR_OAUTH_REDIRECT_URI, - LINEAR_WEBHOOK_SECRET, - PORT, -} from "../config"; -import type { LinearWebhookEvent } from "../linear-types"; - -// Create Hono app -const router = new Hono(); - -// Mount ActorCore -const { router: actorRouter, injectWebSocket } = createRouter(app); -router.route(BASE_PATH, actorRouter); - -// Setup OAuth -const openidConfig = new openidClient.Configuration( - { - issuer: "https://linear.app", - authorization_endpoint: "https://linear.app/oauth/authorize", - token_endpoint: "https://api.linear.app/oauth/token", - }, - LINEAR_OAUTH_CLIENT_ID, - { - client_secret: LINEAR_OAUTH_CLIENT_AUTHENTICATION, - }, -); - -// Step 1: Connect Linear -router.get("/connect-linear", async (c) => { - // Setup session - // - // Nonce is required to verify that we generated this request - const sessionId = crypto.randomUUID(); - const nonce = openidClient.randomNonce(); - const oauthState = btoa( - JSON.stringify({ sessionId, nonce } satisfies OAuthExpectedState), - ); - - await actorClient.oauthSession.create(sessionId, { - input: { nonce, oauthState }, - }); - - const parameters: Record = { - redirect_uri: LINEAR_OAUTH_REDIRECT_URI, - - state: oauthState, - - // See https://linear.app/developers/agents#actor-and-scopes - // - // app:assignable = lets tickets be assigned to your agent - // app:mentionable = lets your agent be mentioned - scope: "read write app:assignable app:mentionable", - - // IMPORTANT: Changes the authentication type - actor: "app", - }; - - const redirectTo: URL = openidClient.buildAuthorizationUrl( - openidConfig, - parameters, - ); - - console.log("Redirecting to OAuth", redirectTo); - - return c.redirect(redirectTo.href); -}); - -// Step 2: -// GET https://example.com/oauth/callback?code=9a5190f637d8b1ad0ca92ab3ec4c0d033ad6c862&state=b1ad0ca92 HTTP/1.1 -router.get("/oauth/callback/linear", async (c) => { - const stateRaw = c.req.query("state"); - const state = JSON.parse(atob(stateRaw!)) as OAuthExpectedState; - - // Validate that the OAuth session has the same nonce - const expectedState = await actorClient.oauthSession - .get(state.sessionId) - .getOAuthState(); - - console.log("Validating tokens"); - const tokens: openidClient.TokenEndpointResponse = - await openidClient.authorizationCodeGrant( - openidConfig, - // HACK: Fix protocol when hosting locally - new URL(c.req.url.replace("http://", "https://")), - { - expectedState, - }, - ); - - console.log("Fetching app user ID"); - const linearClient = new LinearClient({ accessToken: tokens.access_token }); - const viewer = await linearClient.viewer; - const appUserId = viewer.id; - - console.log(`Saving access token ${appUserId}`); - await actorClient.linearAppUser - .getOrCreate(appUserId) - .setAccessToken(tokens.access_token); - - return c.text(`Successfully linked with app user ID ${appUserId}`); -}); - -// Step 3: Receive events from Linear -router.post("/webhook/linear", async (c) => { - const rawBody = await c.req.text(); - - // Verify signature - const signature = c.req.header("linear-signature"); - const computedSignature = crypto - .createHmac("sha256", LINEAR_WEBHOOK_SECRET) - .update(rawBody) - .digest("hex"); - if (signature !== computedSignature) { - throw new Error("Signature does not match"); - } - - // Parse event - const event: LinearWebhookEvent = JSON.parse(rawBody); - console.log( - `received linear webhook: ${event.appUserId} - ${event.type} - ${event.action}`, - ); - - // Create actor (if needed) and sendt o actor - if (event.type === "AppUserNotification") { - console.log("App user event", JSON.parse(rawBody)); - const notification = event.notification; - const issueId = event.notification.issueId; - - // Get issue agent - const issueAgent = actorClient.issueAgent.getOrCreate(issueId, { - createWithInput: { issueId }, - }); - - // Forward event - switch (notification.type) { - case "issueMention": - issueAgent.issueMention(event.appUserId, notification.issue); - break; - case "issueEmojiReaction": - issueAgent.issueEmojiReaction( - event.appUserId, - notification.issue, - notification.reactionEmoji || "", - ); - break; - case "issueCommentMention": - issueAgent.issueCommentMention( - event.appUserId, - notification.issue, - notification.comment!, - ); - break; - case "issueCommentReaction": - issueAgent.issueCommentReaction( - event.appUserId, - notification.issue, - notification.comment!, - notification.reactionEmoji!, - ); - break; - case "issueAssignedToYou": - issueAgent.issueAssignedToYou( - event.appUserId, - notification.issue, - ); - break; - case "issueUnassignedFromYou": - issueAgent.issueUnassignedFromYou( - event.appUserId, - notification.issue, - ); - break; - case "issueNewComment": - issueAgent.issueNewComment( - event.appUserId, - notification.issue, - notification.comment!, - ); - break; - case "issueStatusChanged": - issueAgent.issueStatusChanged( - event.appUserId, - notification.issue, - ); - break; - default: - console.warn( - `Unknown notification event: ${event.type} - ${event.action}`, - ); - } - } else { - console.warn(`Unknown webhook event: ${event.type} - ${event.action}`); - } - - return c.text("ok"); -}); - -router.get("/health", (c) => { - return c.text("ok"); -}); - -// Start the server -const server = serve( - { - fetch: router.fetch, - port: PORT, - }, - (info) => { - console.log(`Running on port ${info.port}`); - console.log( - `Start by visiting http://127.0.0.1:${info.port}/connect-linear`, - ); - }, -); -injectWebSocket(server); diff --git a/examples/linear-agent-starter/tsconfig.json b/examples/linear-agent-starter/tsconfig.json deleted file mode 100644 index b9983b24b6..0000000000 --- a/examples/linear-agent-starter/tsconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "compilerOptions": { - "target": "esnext", - "module": "esnext", - "strict": true, - "skipLibCheck": true, - "esModuleInterop": false, - "allowSyntheticDefaultImports": true, - "stripInternal": true, - "moduleResolution": "bundler", - "lib": ["ESNext", "DOM"], - "types": ["node"] - } -} diff --git a/examples/linear-agent-starter/yarn.lock b/examples/linear-agent-starter/yarn.lock deleted file mode 100644 index 65af444453..0000000000 --- a/examples/linear-agent-starter/yarn.lock +++ /dev/null @@ -1,3701 +0,0 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 8 - cacheKey: 10c0 - -"@actor-core/cli@npm:0.9.0-rc.1": - version: 0.9.0-rc.1 - resolution: "@actor-core/cli@npm:0.9.0-rc.1" - dependencies: - "@actor-core/nodejs": "npm:^0.9.0-rc.1" - "@sentry/profiling-node": "npm:^9.3.0" - bundle-require: "npm:^5.1.0" - chokidar: "npm:^4.0.3" - esbuild: "npm:^0.25.1" - invariant: "npm:^2.2.4" - open: "npm:^10.1.0" - yoga-wasm-web: "npm:0.3.3" - bin: - ac: ./dist/cli.js - actor-core: ./dist/cli.js - checksum: 10c0/0fedec2cc3e8d194bd1ee021f0c53858392169153357f7f1074d3b9c88a247f2b8b36ebb73bced624927c6d881697d65947c7fbfb81a2eeea623cd870c9ee73a - languageName: node - linkType: hard - -"@actor-core/nodejs@npm:0.9.0-rc.1, @actor-core/nodejs@npm:^0.9.0-rc.1": - version: 0.9.0-rc.1 - resolution: "@actor-core/nodejs@npm:0.9.0-rc.1" - dependencies: - "@hono/node-server": "npm:^1.13.8" - "@hono/node-ws": "npm:^1.0.8" - zod: "npm:^3.24.2" - peerDependencies: - "@actor-core/file-system": "*" - "@actor-core/memory": "*" - actor-core: "*" - checksum: 10c0/e7e3b722ebb2062eeec5050a0e8c7ecc4207267eec946f2d4eccc79c803540809d092a3ebccab91ebf8929612f70f5b2f4a6c16c5745434e78c015315e655f7f - languageName: node - linkType: hard - -"@actor-core/rivet@npm:0.9.0-rc.1": - version: 0.9.0-rc.1 - resolution: "@actor-core/rivet@npm:0.9.0-rc.1" - dependencies: - hono: "npm:^4.7.0" - invariant: "npm:^2.2.4" - zod: "npm:^3.24.2" - peerDependencies: - actor-core: "*" - checksum: 10c0/05271ec2c68c9648a5edb218087322ef372f14ccdfaadf9922ef680865bb4afb27120055ff8d9b36381866c1d82e5d8fae94d3c4e3aea62b5c406327c15f0bb2 - languageName: node - linkType: hard - -"@ai-sdk/anthropic@npm:^1.2.12": - version: 1.2.12 - resolution: "@ai-sdk/anthropic@npm:1.2.12" - dependencies: - "@ai-sdk/provider": "npm:1.1.3" - "@ai-sdk/provider-utils": "npm:2.2.8" - peerDependencies: - zod: ^3.0.0 - checksum: 10c0/da13e1ed3c03efe207dbb0fd5fe9f399e4119e6687ec1096418a33a7eeea3c5f912a51c74b185bba3c203b15ee0c1b9cdf649711815ff8e769e31af266ac00fb - languageName: node - linkType: hard - -"@ai-sdk/openai@npm:^1.3.22": - version: 1.3.22 - resolution: "@ai-sdk/openai@npm:1.3.22" - dependencies: - "@ai-sdk/provider": "npm:1.1.3" - "@ai-sdk/provider-utils": "npm:2.2.8" - peerDependencies: - zod: ^3.0.0 - checksum: 10c0/bcc73a84bebd15aa54568c3c77cedd5f999e282c5be180d5e28ebc789f8873dd0a74d87f1ec4a0f16e3e61b658c3b0734835daf176ed910966246db73c72b468 - languageName: node - linkType: hard - -"@ai-sdk/provider-utils@npm:2.2.8": - version: 2.2.8 - resolution: "@ai-sdk/provider-utils@npm:2.2.8" - dependencies: - "@ai-sdk/provider": "npm:1.1.3" - nanoid: "npm:^3.3.8" - secure-json-parse: "npm:^2.7.0" - peerDependencies: - zod: ^3.23.8 - checksum: 10c0/34c72bf5f23f2d3e7aef496da7099422ba3b3ff243c35511853e16c3f1528717500262eea32b19e3e09bc4452152a5f31e650512f53f08a5f5645d907bff429e - languageName: node - linkType: hard - -"@ai-sdk/provider@npm:1.1.3": - version: 1.1.3 - resolution: "@ai-sdk/provider@npm:1.1.3" - dependencies: - json-schema: "npm:^0.4.0" - checksum: 10c0/40e080e223328e7c89829865e9c48f4ce8442a6a59f7ed5dfbdb4f63e8d859a76641e2d31e91970dd389bddb910f32ec7c3dbb0ce583c119e5a1e614ea7b8bc4 - languageName: node - linkType: hard - -"@ai-sdk/react@npm:1.2.12": - version: 1.2.12 - resolution: "@ai-sdk/react@npm:1.2.12" - dependencies: - "@ai-sdk/provider-utils": "npm:2.2.8" - "@ai-sdk/ui-utils": "npm:1.2.11" - swr: "npm:^2.2.5" - throttleit: "npm:2.1.0" - peerDependencies: - react: ^18 || ^19 || ^19.0.0-rc - zod: ^3.23.8 - peerDependenciesMeta: - zod: - optional: true - checksum: 10c0/5422feb4ffeebd3287441cf658733e9ad7f9081fc279e85f57700d7fe9f4ed8a0504789c1be695790df44b28730e525cf12acf0f52bfa5adecc561ffd00cb2a5 - languageName: node - linkType: hard - -"@ai-sdk/ui-utils@npm:1.2.11": - version: 1.2.11 - resolution: "@ai-sdk/ui-utils@npm:1.2.11" - dependencies: - "@ai-sdk/provider": "npm:1.1.3" - "@ai-sdk/provider-utils": "npm:2.2.8" - zod-to-json-schema: "npm:^3.24.1" - peerDependencies: - zod: ^3.23.8 - checksum: 10c0/de0a10f9e16010126a21a1690aaf56d545b9c0f8d8b2cc33ffd22c2bb2e914949acb9b3f86e0e39a0e4b0d4f24db12e2b094045e34b311de0c8f84bfab48cc92 - languageName: node - linkType: hard - -"@asteasolutions/zod-to-openapi@npm:^7.3.0": - version: 7.3.2 - resolution: "@asteasolutions/zod-to-openapi@npm:7.3.2" - dependencies: - openapi3-ts: "npm:^4.1.2" - peerDependencies: - zod: ^3.20.2 - checksum: 10c0/a30b55f0b8468eb9e75cb9e9124480717833f09cffe27d7af76766420d0829572938827ee806186b1847511097b271426f1e68ca472d03cfbfeb077e09fe1b93 - languageName: node - linkType: hard - -"@cbor-extract/cbor-extract-darwin-arm64@npm:2.2.0": - version: 2.2.0 - resolution: "@cbor-extract/cbor-extract-darwin-arm64@npm:2.2.0" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@cbor-extract/cbor-extract-darwin-x64@npm:2.2.0": - version: 2.2.0 - resolution: "@cbor-extract/cbor-extract-darwin-x64@npm:2.2.0" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@cbor-extract/cbor-extract-linux-arm64@npm:2.2.0": - version: 2.2.0 - resolution: "@cbor-extract/cbor-extract-linux-arm64@npm:2.2.0" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"@cbor-extract/cbor-extract-linux-arm@npm:2.2.0": - version: 2.2.0 - resolution: "@cbor-extract/cbor-extract-linux-arm@npm:2.2.0" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@cbor-extract/cbor-extract-linux-x64@npm:2.2.0": - version: 2.2.0 - resolution: "@cbor-extract/cbor-extract-linux-x64@npm:2.2.0" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"@cbor-extract/cbor-extract-win32-x64@npm:2.2.0": - version: 2.2.0 - resolution: "@cbor-extract/cbor-extract-win32-x64@npm:2.2.0" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/aix-ppc64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/aix-ppc64@npm:0.25.5" - conditions: os=aix & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/android-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/android-arm64@npm:0.18.20" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/android-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/android-arm64@npm:0.25.5" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/android-arm@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/android-arm@npm:0.18.20" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - -"@esbuild/android-arm@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/android-arm@npm:0.25.5" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - -"@esbuild/android-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/android-x64@npm:0.18.20" - conditions: os=android & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/android-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/android-x64@npm:0.25.5" - conditions: os=android & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/darwin-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/darwin-arm64@npm:0.18.20" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/darwin-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/darwin-arm64@npm:0.25.5" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/darwin-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/darwin-x64@npm:0.18.20" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/darwin-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/darwin-x64@npm:0.25.5" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/freebsd-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/freebsd-arm64@npm:0.18.20" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/freebsd-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/freebsd-arm64@npm:0.25.5" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/freebsd-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/freebsd-x64@npm:0.18.20" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/freebsd-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/freebsd-x64@npm:0.25.5" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/linux-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-arm64@npm:0.18.20" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/linux-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-arm64@npm:0.25.5" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/linux-arm@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-arm@npm:0.18.20" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@esbuild/linux-arm@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-arm@npm:0.25.5" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@esbuild/linux-ia32@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-ia32@npm:0.18.20" - conditions: os=linux & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/linux-ia32@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-ia32@npm:0.25.5" - conditions: os=linux & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/linux-loong64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-loong64@npm:0.18.20" - conditions: os=linux & cpu=loong64 - languageName: node - linkType: hard - -"@esbuild/linux-loong64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-loong64@npm:0.25.5" - conditions: os=linux & cpu=loong64 - languageName: node - linkType: hard - -"@esbuild/linux-mips64el@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-mips64el@npm:0.18.20" - conditions: os=linux & cpu=mips64el - languageName: node - linkType: hard - -"@esbuild/linux-mips64el@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-mips64el@npm:0.25.5" - conditions: os=linux & cpu=mips64el - languageName: node - linkType: hard - -"@esbuild/linux-ppc64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-ppc64@npm:0.18.20" - conditions: os=linux & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/linux-ppc64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-ppc64@npm:0.25.5" - conditions: os=linux & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/linux-riscv64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-riscv64@npm:0.18.20" - conditions: os=linux & cpu=riscv64 - languageName: node - linkType: hard - -"@esbuild/linux-riscv64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-riscv64@npm:0.25.5" - conditions: os=linux & cpu=riscv64 - languageName: node - linkType: hard - -"@esbuild/linux-s390x@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-s390x@npm:0.18.20" - conditions: os=linux & cpu=s390x - languageName: node - linkType: hard - -"@esbuild/linux-s390x@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-s390x@npm:0.25.5" - conditions: os=linux & cpu=s390x - languageName: node - linkType: hard - -"@esbuild/linux-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-x64@npm:0.18.20" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/linux-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-x64@npm:0.25.5" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/netbsd-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/netbsd-arm64@npm:0.25.5" - conditions: os=netbsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/netbsd-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/netbsd-x64@npm:0.18.20" - conditions: os=netbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/netbsd-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/netbsd-x64@npm:0.25.5" - conditions: os=netbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/openbsd-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/openbsd-arm64@npm:0.25.5" - conditions: os=openbsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/openbsd-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/openbsd-x64@npm:0.18.20" - conditions: os=openbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/openbsd-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/openbsd-x64@npm:0.25.5" - conditions: os=openbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/sunos-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/sunos-x64@npm:0.18.20" - conditions: os=sunos & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/sunos-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/sunos-x64@npm:0.25.5" - conditions: os=sunos & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/win32-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/win32-arm64@npm:0.18.20" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/win32-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/win32-arm64@npm:0.25.5" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/win32-ia32@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/win32-ia32@npm:0.18.20" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/win32-ia32@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/win32-ia32@npm:0.25.5" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/win32-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/win32-x64@npm:0.18.20" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/win32-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/win32-x64@npm:0.25.5" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@graphql-typed-document-node/core@npm:^3.1.0": - version: 3.2.0 - resolution: "@graphql-typed-document-node/core@npm:3.2.0" - peerDependencies: - graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 10c0/94e9d75c1f178bbae8d874f5a9361708a3350c8def7eaeb6920f2c820e82403b7d4f55b3735856d68e145e86c85cbfe2adc444fdc25519cd51f108697e99346c - languageName: node - linkType: hard - -"@hono/node-server@npm:^1.13.8": - version: 1.14.3 - resolution: "@hono/node-server@npm:1.14.3" - peerDependencies: - hono: ^4 - checksum: 10c0/2e873ed38be44bd2499ffd6e592782edd9216475935d992119ad1d3f61f14cb39dc8fe79d1ed5d7d8caeef1d9fd84b36f9715add0b9f98c3d040b5cc9ef872f8 - languageName: node - linkType: hard - -"@hono/node-ws@npm:^1.0.8": - version: 1.1.4 - resolution: "@hono/node-ws@npm:1.1.4" - dependencies: - ws: "npm:^8.17.0" - peerDependencies: - "@hono/node-server": ^1.11.1 - hono: ^4.6.0 - checksum: 10c0/7bd8f72af2dae0319fbe1ffa831f65456ec3342d7607bfb45d4071d8412c9c2e8faa533d6dcf49c603508e4d353b65920da618d07d5a129e6634793298f2f940 - languageName: node - linkType: hard - -"@hono/zod-openapi@npm:^0.19.6": - version: 0.19.7 - resolution: "@hono/zod-openapi@npm:0.19.7" - dependencies: - "@asteasolutions/zod-to-openapi": "npm:^7.3.0" - "@hono/zod-validator": "npm:^0.6.0" - peerDependencies: - hono: ">=4.3.6" - zod: 3.* - checksum: 10c0/4cb381cba6f93deaf6f53cfccb968252fa5a4b88628a72c0e99792592e6e24fba1b1abf20230191bbca4d038dcf9ebbb9586ad41f5572f354ea778ffbead34e7 - languageName: node - linkType: hard - -"@hono/zod-validator@npm:^0.6.0": - version: 0.6.0 - resolution: "@hono/zod-validator@npm:0.6.0" - peerDependencies: - hono: ">=3.9.0" - zod: ^3.19.1 - checksum: 10c0/8c9c96b5e1311a45de5789b12fda7240862144aecca3fc6f5936bc0e3d710ddaa90b736c91dae657191d6a6510f68828e98a5cc2e342d3096c01d2b5a65a71af - languageName: node - linkType: hard - -"@isaacs/cliui@npm:^8.0.2": - version: 8.0.2 - resolution: "@isaacs/cliui@npm:8.0.2" - dependencies: - string-width: "npm:^5.1.2" - string-width-cjs: "npm:string-width@^4.2.0" - strip-ansi: "npm:^7.0.1" - strip-ansi-cjs: "npm:strip-ansi@^6.0.1" - wrap-ansi: "npm:^8.1.0" - wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" - checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e - languageName: node - linkType: hard - -"@isaacs/fs-minipass@npm:^4.0.0": - version: 4.0.1 - resolution: "@isaacs/fs-minipass@npm:4.0.1" - dependencies: - minipass: "npm:^7.0.4" - checksum: 10c0/c25b6dc1598790d5b55c0947a9b7d111cfa92594db5296c3b907e2f533c033666f692a3939eadac17b1c7c40d362d0b0635dc874cbfe3e70db7c2b07cc97a5d2 - languageName: node - linkType: hard - -"@jridgewell/sourcemap-codec@npm:^1.5.0": - version: 1.5.0 - resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" - checksum: 10c0/2eb864f276eb1096c3c11da3e9bb518f6d9fc0023c78344cdc037abadc725172c70314bdb360f2d4b7bffec7f5d657ce006816bc5d4ecb35e61b66132db00c18 - languageName: node - linkType: hard - -"@linear/sdk@npm:^40.0.0": - version: 40.0.0 - resolution: "@linear/sdk@npm:40.0.0" - dependencies: - "@graphql-typed-document-node/core": "npm:^3.1.0" - graphql: "npm:^15.4.0" - isomorphic-unfetch: "npm:^3.1.0" - checksum: 10c0/133a416c535c32c00018a52d494038c606d3ab24da815e73a69787227ee823ec807d8856e49a753569acf72bb1e94e2eea06387175196c5f8b418a507119a541 - languageName: node - linkType: hard - -"@npmcli/agent@npm:^3.0.0": - version: 3.0.0 - resolution: "@npmcli/agent@npm:3.0.0" - dependencies: - agent-base: "npm:^7.1.0" - http-proxy-agent: "npm:^7.0.0" - https-proxy-agent: "npm:^7.0.1" - lru-cache: "npm:^10.0.1" - socks-proxy-agent: "npm:^8.0.3" - checksum: 10c0/efe37b982f30740ee77696a80c196912c274ecd2cb243bc6ae7053a50c733ce0f6c09fda085145f33ecf453be19654acca74b69e81eaad4c90f00ccffe2f9271 - languageName: node - linkType: hard - -"@npmcli/fs@npm:^4.0.0": - version: 4.0.0 - resolution: "@npmcli/fs@npm:4.0.0" - dependencies: - semver: "npm:^7.3.5" - checksum: 10c0/c90935d5ce670c87b6b14fab04a965a3b8137e585f8b2a6257263bd7f97756dd736cb165bb470e5156a9e718ecd99413dccc54b1138c1a46d6ec7cf325982fe5 - languageName: node - linkType: hard - -"@opentelemetry/api-logs@npm:0.57.2": - version: 0.57.2 - resolution: "@opentelemetry/api-logs@npm:0.57.2" - dependencies: - "@opentelemetry/api": "npm:^1.3.0" - checksum: 10c0/1e514d3fd4ca68e7e8b008794a95ee0562a5d9e1d3ebb02647b245afaa6c2d72cc14e99e3ea47a1d1007f8a965c62bfb6170e1aa26756230bea063cfde2898bf - languageName: node - linkType: hard - -"@opentelemetry/api@npm:1.9.0, @opentelemetry/api@npm:^1.3.0, @opentelemetry/api@npm:^1.9.0": - version: 1.9.0 - resolution: "@opentelemetry/api@npm:1.9.0" - checksum: 10c0/9aae2fe6e8a3a3eeb6c1fdef78e1939cf05a0f37f8a4fae4d6bf2e09eb1e06f966ece85805626e01ba5fab48072b94f19b835449e58b6d26720ee19a58298add - languageName: node - linkType: hard - -"@opentelemetry/context-async-hooks@npm:^1.30.1": - version: 1.30.1 - resolution: "@opentelemetry/context-async-hooks@npm:1.30.1" - peerDependencies: - "@opentelemetry/api": ">=1.0.0 <1.10.0" - checksum: 10c0/3e8114d360060a5225226d2fcd8df08cd542246003790a7f011c0774bc60b8a931f46f4c6673f3977a7d9bba717de6ee028cae51b752c2567053d7f46ed3eba3 - languageName: node - linkType: hard - -"@opentelemetry/core@npm:1.30.1, @opentelemetry/core@npm:^1.1.0, @opentelemetry/core@npm:^1.26.0, @opentelemetry/core@npm:^1.30.1, @opentelemetry/core@npm:^1.8.0": - version: 1.30.1 - resolution: "@opentelemetry/core@npm:1.30.1" - dependencies: - "@opentelemetry/semantic-conventions": "npm:1.28.0" - peerDependencies: - "@opentelemetry/api": ">=1.0.0 <1.10.0" - checksum: 10c0/4c25ba50a6137c2ba9ca563fb269378f3c9ca6fd1b3f15dbb6eff78eebf5656f281997cbb7be8e51c01649fd6ad091083fcd8a42dd9b5dfac907dc06d7cfa092 - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-amqplib@npm:^0.46.1": - version: 0.46.1 - resolution: "@opentelemetry/instrumentation-amqplib@npm:0.46.1" - dependencies: - "@opentelemetry/core": "npm:^1.8.0" - "@opentelemetry/instrumentation": "npm:^0.57.1" - "@opentelemetry/semantic-conventions": "npm:^1.27.0" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/4a8b870ccaa64cfd200663ec14385aca7eeb7146124d82e566f3d48678f237c9a56661ae3401345fe0dce5c56366ae02a312dc7905eb4fd6e073df2cface30fb - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-connect@npm:0.43.1": - version: 0.43.1 - resolution: "@opentelemetry/instrumentation-connect@npm:0.43.1" - dependencies: - "@opentelemetry/core": "npm:^1.8.0" - "@opentelemetry/instrumentation": "npm:^0.57.1" - "@opentelemetry/semantic-conventions": "npm:^1.27.0" - "@types/connect": "npm:3.4.38" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/a7e2629fbfa775f2d1a6b2c9387e27809db16177cf6de89159017d7353c270c6c84d81550c58ccc51ea72c2304b1fcb911499440451d8df6954cc1f4e654eb64 - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-dataloader@npm:0.16.1": - version: 0.16.1 - resolution: "@opentelemetry/instrumentation-dataloader@npm:0.16.1" - dependencies: - "@opentelemetry/instrumentation": "npm:^0.57.1" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/83bd0267672cc3e8709401e1f107612aed3bb72faedfed76fe25e174b19c41f65d503bc3a666ba0872bbef8c31adcefb8884982f785fa3b0df28eec40b6578aa - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-express@npm:0.47.1": - version: 0.47.1 - resolution: "@opentelemetry/instrumentation-express@npm:0.47.1" - dependencies: - "@opentelemetry/core": "npm:^1.8.0" - "@opentelemetry/instrumentation": "npm:^0.57.1" - "@opentelemetry/semantic-conventions": "npm:^1.27.0" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/eca448eb088857c7c0c7d0a1875b9e20a990b23e2f64355d2e645618d3f5c038efb9d605009a6d8fa1e05243d0ccef14b9aa1effffee693fd071de3cc39ad3d1 - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-fs@npm:0.19.1": - version: 0.19.1 - resolution: "@opentelemetry/instrumentation-fs@npm:0.19.1" - dependencies: - "@opentelemetry/core": "npm:^1.8.0" - "@opentelemetry/instrumentation": "npm:^0.57.1" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/8bf714658c0fcc34ba7db4c28af3196690f756a9b4fb6d1b6cab59938a7b5c1e40e834c518b39085e744915c0c384ca6d997a8a97901955732acf3af0cba6e7f - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-generic-pool@npm:0.43.1": - version: 0.43.1 - resolution: "@opentelemetry/instrumentation-generic-pool@npm:0.43.1" - dependencies: - "@opentelemetry/instrumentation": "npm:^0.57.1" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/bdc95146d1f6f5dcf5922af8161c4954b9feeb505a01c5e61b1246ed67909dc1f6e72ad067839f085a4977e863246e7e4b468c814cf4104f35fcc20fb570eac2 - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-graphql@npm:0.47.1": - version: 0.47.1 - resolution: "@opentelemetry/instrumentation-graphql@npm:0.47.1" - dependencies: - "@opentelemetry/instrumentation": "npm:^0.57.1" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/d5cfeb668b5ea4e4d97d8433c642457ac9f7f2023278a84a183b4c4c2cc43bbae3eac916ff7176ef8492661877560b519663c52eb2fad0a8a1f00718a0449aa6 - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-hapi@npm:0.45.2": - version: 0.45.2 - resolution: "@opentelemetry/instrumentation-hapi@npm:0.45.2" - dependencies: - "@opentelemetry/core": "npm:^1.8.0" - "@opentelemetry/instrumentation": "npm:^0.57.1" - "@opentelemetry/semantic-conventions": "npm:^1.27.0" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/bb491327ce86d8f1f7e2a12621a00dbf921e1fc3e9b64f975fc23e443d92bcd6ef779b34349214871763d459650da219c5e23bb1fdd1bc261fa0f92190521b2e - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-http@npm:0.57.2": - version: 0.57.2 - resolution: "@opentelemetry/instrumentation-http@npm:0.57.2" - dependencies: - "@opentelemetry/core": "npm:1.30.1" - "@opentelemetry/instrumentation": "npm:0.57.2" - "@opentelemetry/semantic-conventions": "npm:1.28.0" - forwarded-parse: "npm:2.1.2" - semver: "npm:^7.5.2" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/b95a1b61cddabd32358fa565a4fcf5c17e8340907b171dcdf2a104533c9afdee821efa7b82dabb3123318dcc66272b0a7b8c37c44fc87e593cb8138a7a63fc23 - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-ioredis@npm:0.47.1": - version: 0.47.1 - resolution: "@opentelemetry/instrumentation-ioredis@npm:0.47.1" - dependencies: - "@opentelemetry/instrumentation": "npm:^0.57.1" - "@opentelemetry/redis-common": "npm:^0.36.2" - "@opentelemetry/semantic-conventions": "npm:^1.27.0" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/ec741778041cecc133a143292d66631c99311bf098db8f03276a48b87fe18826eec4513e4de70bb555ef50268db6520442e9a2f7752f7ea9b5a3e8363fecb8c9 - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-kafkajs@npm:0.7.1": - version: 0.7.1 - resolution: "@opentelemetry/instrumentation-kafkajs@npm:0.7.1" - dependencies: - "@opentelemetry/instrumentation": "npm:^0.57.1" - "@opentelemetry/semantic-conventions": "npm:^1.27.0" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/440a479ec65414da706f15b5c2ff82235ea8b11701e811ae235af5e8f01bee7e639223243e9f18550ce55cc94b8cdaa8a72297ded55f1c7993f1d95488c2b02e - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-knex@npm:0.44.1": - version: 0.44.1 - resolution: "@opentelemetry/instrumentation-knex@npm:0.44.1" - dependencies: - "@opentelemetry/instrumentation": "npm:^0.57.1" - "@opentelemetry/semantic-conventions": "npm:^1.27.0" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/75dcbda2c412cc448ac95238899d92846bda14bb21a1c9e9bc0c51fd48dcedb6064c2a8ab9e53d112945748d50513ecda13afbc4c0f24a884674d2a485f0efcd - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-koa@npm:0.47.1": - version: 0.47.1 - resolution: "@opentelemetry/instrumentation-koa@npm:0.47.1" - dependencies: - "@opentelemetry/core": "npm:^1.8.0" - "@opentelemetry/instrumentation": "npm:^0.57.1" - "@opentelemetry/semantic-conventions": "npm:^1.27.0" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/a1c5433da1265f1f8da3e46ebe085a3ddba3e16f43c5f44bd41082a0839f6bdf9a6a737b80b0d2f2a05d1ef2c23e2b0a4f7e55858bf1e32570b4c150c69135bc - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-lru-memoizer@npm:0.44.1": - version: 0.44.1 - resolution: "@opentelemetry/instrumentation-lru-memoizer@npm:0.44.1" - dependencies: - "@opentelemetry/instrumentation": "npm:^0.57.1" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/5728d0b6ed560ba8426546ab30ef251cbe9f25a130abc8bea0d7635b51cc29fbade4d00c7b1869fa0543fe54891799483fe0f6fb4073d1bf5d12dbdd543aaae5 - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-mongodb@npm:0.52.0": - version: 0.52.0 - resolution: "@opentelemetry/instrumentation-mongodb@npm:0.52.0" - dependencies: - "@opentelemetry/instrumentation": "npm:^0.57.1" - "@opentelemetry/semantic-conventions": "npm:^1.27.0" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/dcd072a296369a6b254a809e3708e5f9842ac9f8c61700bfa2014872fa6e6ca65adfa5efdbf9021df57e749dea2cddd828351e73cb581370b8b97693c06df7e8 - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-mongoose@npm:0.46.1": - version: 0.46.1 - resolution: "@opentelemetry/instrumentation-mongoose@npm:0.46.1" - dependencies: - "@opentelemetry/core": "npm:^1.8.0" - "@opentelemetry/instrumentation": "npm:^0.57.1" - "@opentelemetry/semantic-conventions": "npm:^1.27.0" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/69378d41df172c2edb8b36042e751936837bb1cbee11ee72a3d1608c6d7f609d79beec2020b25de72086553ad9d85347642c4066e0b4e96d442513b29ac4f0aa - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-mysql2@npm:0.45.2": - version: 0.45.2 - resolution: "@opentelemetry/instrumentation-mysql2@npm:0.45.2" - dependencies: - "@opentelemetry/instrumentation": "npm:^0.57.1" - "@opentelemetry/semantic-conventions": "npm:^1.27.0" - "@opentelemetry/sql-common": "npm:^0.40.1" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/8ac62064b32facfddd7d47ba0bce9689d2277ba4ef74348655faffe818522c919654c5bf1a5fac211a75f2093fbd588a14cba278c353da2f60d1919d58d419aa - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-mysql@npm:0.45.1": - version: 0.45.1 - resolution: "@opentelemetry/instrumentation-mysql@npm:0.45.1" - dependencies: - "@opentelemetry/instrumentation": "npm:^0.57.1" - "@opentelemetry/semantic-conventions": "npm:^1.27.0" - "@types/mysql": "npm:2.15.26" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/c820a6929fe2e010dacb8962d40fdb8c9ac95c265efc74f478eadc021b2a3add9ce8d303c4bda20af01327564f487c9e052e710d9e975d7f17a5918d802d7ae4 - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-pg@npm:0.51.1": - version: 0.51.1 - resolution: "@opentelemetry/instrumentation-pg@npm:0.51.1" - dependencies: - "@opentelemetry/core": "npm:^1.26.0" - "@opentelemetry/instrumentation": "npm:^0.57.1" - "@opentelemetry/semantic-conventions": "npm:^1.27.0" - "@opentelemetry/sql-common": "npm:^0.40.1" - "@types/pg": "npm:8.6.1" - "@types/pg-pool": "npm:2.0.6" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/fff3dcc092b959601a20c20e19c27d39d6386e6bc2b7014c1be5a5e22c0e275bf9980dad758b1f7824b1448a6178e13938b6bb2da53095f410fbb4d248b5ede6 - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-redis-4@npm:0.46.1": - version: 0.46.1 - resolution: "@opentelemetry/instrumentation-redis-4@npm:0.46.1" - dependencies: - "@opentelemetry/instrumentation": "npm:^0.57.1" - "@opentelemetry/redis-common": "npm:^0.36.2" - "@opentelemetry/semantic-conventions": "npm:^1.27.0" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/df0bdd865e254c9b4c0339ce5aabf3698d99b8ab8cf8ea1aa57ffa13620f2193fda247ed43ec4ccc6edadab1ffec5cc263038ab6f3c9e96ef000ee232b9181f8 - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-tedious@npm:0.18.1": - version: 0.18.1 - resolution: "@opentelemetry/instrumentation-tedious@npm:0.18.1" - dependencies: - "@opentelemetry/instrumentation": "npm:^0.57.1" - "@opentelemetry/semantic-conventions": "npm:^1.27.0" - "@types/tedious": "npm:^4.0.14" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/fda9ac4dc89998a2cf739a70f06b1d6eebf98fe22713dc3fbca4a1119dc289d83c91ada4a3cea37f39a34c69978ae21ff9b599c27beaee128879b993677696dc - languageName: node - linkType: hard - -"@opentelemetry/instrumentation-undici@npm:0.10.1": - version: 0.10.1 - resolution: "@opentelemetry/instrumentation-undici@npm:0.10.1" - dependencies: - "@opentelemetry/core": "npm:^1.8.0" - "@opentelemetry/instrumentation": "npm:^0.57.1" - peerDependencies: - "@opentelemetry/api": ^1.7.0 - checksum: 10c0/3958f291d14f2f7bb5e3b957487444ffee449d8ea76c973ca09b9669258d37e98b3797c7167190c5038802529cc6b539bdf6efc7887398ec9b53d3ba51c90bda - languageName: node - linkType: hard - -"@opentelemetry/instrumentation@npm:0.57.2, @opentelemetry/instrumentation@npm:^0.52.0 || ^0.53.0 || ^0.54.0 || ^0.55.0 || ^0.56.0 || ^0.57.0, @opentelemetry/instrumentation@npm:^0.57.1, @opentelemetry/instrumentation@npm:^0.57.2": - version: 0.57.2 - resolution: "@opentelemetry/instrumentation@npm:0.57.2" - dependencies: - "@opentelemetry/api-logs": "npm:0.57.2" - "@types/shimmer": "npm:^1.2.0" - import-in-the-middle: "npm:^1.8.1" - require-in-the-middle: "npm:^7.1.1" - semver: "npm:^7.5.2" - shimmer: "npm:^1.2.1" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/79ca65b66357665d19f89da7027da25ea1c6b55ecdacb0a99534923743c80deb9282870db563de8ae284b13e7e0aab8413efa1937f199deeaef069e07c7e4875 - languageName: node - linkType: hard - -"@opentelemetry/redis-common@npm:^0.36.2": - version: 0.36.2 - resolution: "@opentelemetry/redis-common@npm:0.36.2" - checksum: 10c0/4cb831628551b9f13dca8d65897e300ff7be0e256b77f455a26fb053bbdfc7997b27d066ab1402ca929e7ac77598e0d593f91762d8af9f798c19ba1524e9d078 - languageName: node - linkType: hard - -"@opentelemetry/resources@npm:1.30.1, @opentelemetry/resources@npm:^1.30.1": - version: 1.30.1 - resolution: "@opentelemetry/resources@npm:1.30.1" - dependencies: - "@opentelemetry/core": "npm:1.30.1" - "@opentelemetry/semantic-conventions": "npm:1.28.0" - peerDependencies: - "@opentelemetry/api": ">=1.0.0 <1.10.0" - checksum: 10c0/688e73258283c80662bfa9a858aaf73bf3b832a18d96e546d0dddfa6dcec556cdfa087a1d0df643435293406009e4122d7fb7eeea69aa87b539d3bab756fba74 - languageName: node - linkType: hard - -"@opentelemetry/sdk-trace-base@npm:^1.30.1": - version: 1.30.1 - resolution: "@opentelemetry/sdk-trace-base@npm:1.30.1" - dependencies: - "@opentelemetry/core": "npm:1.30.1" - "@opentelemetry/resources": "npm:1.30.1" - "@opentelemetry/semantic-conventions": "npm:1.28.0" - peerDependencies: - "@opentelemetry/api": ">=1.0.0 <1.10.0" - checksum: 10c0/77019dc3efaeceb41b4c54dd83b92f0ccd81ecceca544cbbe8e0aee4b2c8727724bdb9dcecfe00622c16d60946ae4beb69a5c0e7d85c4bc7ef425bd84f8b970c - languageName: node - linkType: hard - -"@opentelemetry/semantic-conventions@npm:1.28.0": - version: 1.28.0 - resolution: "@opentelemetry/semantic-conventions@npm:1.28.0" - checksum: 10c0/deb8a0f744198071e70fea27143cf7c9f7ecb7e4d7b619488c917834ea09b31543c1c2bcea4ec5f3cf68797f0ef3549609c14e859013d9376400ac1499c2b9cb - languageName: node - linkType: hard - -"@opentelemetry/semantic-conventions@npm:^1.27.0, @opentelemetry/semantic-conventions@npm:^1.30.0": - version: 1.34.0 - resolution: "@opentelemetry/semantic-conventions@npm:1.34.0" - checksum: 10c0/a51a32a5cf5c803bd2125a680d0abacbff632f3b255d0fe52379dac191114a0e8d72a34f9c46c5483ccfe91c4061c309f3cf61a19d11347e2a69779e82cfefd0 - languageName: node - linkType: hard - -"@opentelemetry/sql-common@npm:^0.40.1": - version: 0.40.1 - resolution: "@opentelemetry/sql-common@npm:0.40.1" - dependencies: - "@opentelemetry/core": "npm:^1.1.0" - peerDependencies: - "@opentelemetry/api": ^1.1.0 - checksum: 10c0/60a70358f0c94f610e2995333e96b406626d67d03d38ed03b15a3461ad0f8d64afbf6275cca7cb58fe955ecdce832f3ffc9b73f9d88503bba5d2a620bbd6d351 - languageName: node - linkType: hard - -"@pkgjs/parseargs@npm:^0.11.0": - version: 0.11.0 - resolution: "@pkgjs/parseargs@npm:0.11.0" - checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd - languageName: node - linkType: hard - -"@prisma/instrumentation@npm:6.7.0": - version: 6.7.0 - resolution: "@prisma/instrumentation@npm:6.7.0" - dependencies: - "@opentelemetry/instrumentation": "npm:^0.52.0 || ^0.53.0 || ^0.54.0 || ^0.55.0 || ^0.56.0 || ^0.57.0" - peerDependencies: - "@opentelemetry/api": ^1.8 - checksum: 10c0/32825cd2e16f771efa870a01f99424423e7cf0643dfc3afd6afc2ae4121f814673ab70cfb09a61a453d8b993e398da1dd45fa8822d8ba3c020574c4cd8f35ff8 - languageName: node - linkType: hard - -"@rollup/rollup-android-arm-eabi@npm:4.41.1": - version: 4.41.1 - resolution: "@rollup/rollup-android-arm-eabi@npm:4.41.1" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - -"@rollup/rollup-android-arm64@npm:4.41.1": - version: 4.41.1 - resolution: "@rollup/rollup-android-arm64@npm:4.41.1" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@rollup/rollup-darwin-arm64@npm:4.41.1": - version: 4.41.1 - resolution: "@rollup/rollup-darwin-arm64@npm:4.41.1" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@rollup/rollup-darwin-x64@npm:4.41.1": - version: 4.41.1 - resolution: "@rollup/rollup-darwin-x64@npm:4.41.1" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@rollup/rollup-freebsd-arm64@npm:4.41.1": - version: 4.41.1 - resolution: "@rollup/rollup-freebsd-arm64@npm:4.41.1" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - -"@rollup/rollup-freebsd-x64@npm:4.41.1": - version: 4.41.1 - resolution: "@rollup/rollup-freebsd-x64@npm:4.41.1" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@rollup/rollup-linux-arm-gnueabihf@npm:4.41.1": - version: 4.41.1 - resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.41.1" - conditions: os=linux & cpu=arm & libc=glibc - languageName: node - linkType: hard - -"@rollup/rollup-linux-arm-musleabihf@npm:4.41.1": - version: 4.41.1 - resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.41.1" - conditions: os=linux & cpu=arm & libc=musl - languageName: node - linkType: hard - -"@rollup/rollup-linux-arm64-gnu@npm:4.41.1": - version: 4.41.1 - resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.41.1" - conditions: os=linux & cpu=arm64 & libc=glibc - languageName: node - linkType: hard - -"@rollup/rollup-linux-arm64-musl@npm:4.41.1": - version: 4.41.1 - resolution: "@rollup/rollup-linux-arm64-musl@npm:4.41.1" - conditions: os=linux & cpu=arm64 & libc=musl - languageName: node - linkType: hard - -"@rollup/rollup-linux-loongarch64-gnu@npm:4.41.1": - version: 4.41.1 - resolution: "@rollup/rollup-linux-loongarch64-gnu@npm:4.41.1" - conditions: os=linux & cpu=loong64 & libc=glibc - languageName: node - linkType: hard - -"@rollup/rollup-linux-powerpc64le-gnu@npm:4.41.1": - version: 4.41.1 - resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.41.1" - conditions: os=linux & cpu=ppc64 & libc=glibc - languageName: node - linkType: hard - -"@rollup/rollup-linux-riscv64-gnu@npm:4.41.1": - version: 4.41.1 - resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.41.1" - conditions: os=linux & cpu=riscv64 & libc=glibc - languageName: node - linkType: hard - -"@rollup/rollup-linux-riscv64-musl@npm:4.41.1": - version: 4.41.1 - resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.41.1" - conditions: os=linux & cpu=riscv64 & libc=musl - languageName: node - linkType: hard - -"@rollup/rollup-linux-s390x-gnu@npm:4.41.1": - version: 4.41.1 - resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.41.1" - conditions: os=linux & cpu=s390x & libc=glibc - languageName: node - linkType: hard - -"@rollup/rollup-linux-x64-gnu@npm:4.41.1": - version: 4.41.1 - resolution: "@rollup/rollup-linux-x64-gnu@npm:4.41.1" - conditions: os=linux & cpu=x64 & libc=glibc - languageName: node - linkType: hard - -"@rollup/rollup-linux-x64-musl@npm:4.41.1": - version: 4.41.1 - resolution: "@rollup/rollup-linux-x64-musl@npm:4.41.1" - conditions: os=linux & cpu=x64 & libc=musl - languageName: node - linkType: hard - -"@rollup/rollup-win32-arm64-msvc@npm:4.41.1": - version: 4.41.1 - resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.41.1" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@rollup/rollup-win32-ia32-msvc@npm:4.41.1": - version: 4.41.1 - resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.41.1" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@rollup/rollup-win32-x64-msvc@npm:4.41.1": - version: 4.41.1 - resolution: "@rollup/rollup-win32-x64-msvc@npm:4.41.1" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@sentry-internal/node-cpu-profiler@npm:^2.2.0": - version: 2.2.0 - resolution: "@sentry-internal/node-cpu-profiler@npm:2.2.0" - dependencies: - detect-libc: "npm:^2.0.3" - node-abi: "npm:^3.73.0" - node-gyp: "npm:latest" - checksum: 10c0/8b9d1a0e0db6a3b322370c018a02ec085807ee372cd01de83d077711a6f49c27e1291059b53d239ee00e8c35fff7feeb766b58dcba19a35ffcf5293bd4756672 - languageName: node - linkType: hard - -"@sentry/core@npm:9.22.0": - version: 9.22.0 - resolution: "@sentry/core@npm:9.22.0" - checksum: 10c0/7c1f86778bf34bc9bf5b05d3abbcb107f266824ce293eb8ddebe0765fc12ee46c792f7ba3e7fcf626f4b44db3622413d735e3de21c3f24c3fbe48847c70896e5 - languageName: node - linkType: hard - -"@sentry/node@npm:9.22.0": - version: 9.22.0 - resolution: "@sentry/node@npm:9.22.0" - dependencies: - "@opentelemetry/api": "npm:^1.9.0" - "@opentelemetry/context-async-hooks": "npm:^1.30.1" - "@opentelemetry/core": "npm:^1.30.1" - "@opentelemetry/instrumentation": "npm:^0.57.2" - "@opentelemetry/instrumentation-amqplib": "npm:^0.46.1" - "@opentelemetry/instrumentation-connect": "npm:0.43.1" - "@opentelemetry/instrumentation-dataloader": "npm:0.16.1" - "@opentelemetry/instrumentation-express": "npm:0.47.1" - "@opentelemetry/instrumentation-fs": "npm:0.19.1" - "@opentelemetry/instrumentation-generic-pool": "npm:0.43.1" - "@opentelemetry/instrumentation-graphql": "npm:0.47.1" - "@opentelemetry/instrumentation-hapi": "npm:0.45.2" - "@opentelemetry/instrumentation-http": "npm:0.57.2" - "@opentelemetry/instrumentation-ioredis": "npm:0.47.1" - "@opentelemetry/instrumentation-kafkajs": "npm:0.7.1" - "@opentelemetry/instrumentation-knex": "npm:0.44.1" - "@opentelemetry/instrumentation-koa": "npm:0.47.1" - "@opentelemetry/instrumentation-lru-memoizer": "npm:0.44.1" - "@opentelemetry/instrumentation-mongodb": "npm:0.52.0" - "@opentelemetry/instrumentation-mongoose": "npm:0.46.1" - "@opentelemetry/instrumentation-mysql": "npm:0.45.1" - "@opentelemetry/instrumentation-mysql2": "npm:0.45.2" - "@opentelemetry/instrumentation-pg": "npm:0.51.1" - "@opentelemetry/instrumentation-redis-4": "npm:0.46.1" - "@opentelemetry/instrumentation-tedious": "npm:0.18.1" - "@opentelemetry/instrumentation-undici": "npm:0.10.1" - "@opentelemetry/resources": "npm:^1.30.1" - "@opentelemetry/sdk-trace-base": "npm:^1.30.1" - "@opentelemetry/semantic-conventions": "npm:^1.30.0" - "@prisma/instrumentation": "npm:6.7.0" - "@sentry/core": "npm:9.22.0" - "@sentry/opentelemetry": "npm:9.22.0" - import-in-the-middle: "npm:^1.13.1" - minimatch: "npm:^9.0.0" - checksum: 10c0/4d041e4a4b39824674d65dd8f6bf1261d0541d8200fa6bb5e5ec661b631944b3d4f5730eb06a34675d62aafec8793ab33423b7a45d09caa32d2691c645c88c20 - languageName: node - linkType: hard - -"@sentry/opentelemetry@npm:9.22.0": - version: 9.22.0 - resolution: "@sentry/opentelemetry@npm:9.22.0" - dependencies: - "@sentry/core": "npm:9.22.0" - peerDependencies: - "@opentelemetry/api": ^1.9.0 - "@opentelemetry/context-async-hooks": ^1.30.1 || ^2.0.0 - "@opentelemetry/core": ^1.30.1 || ^2.0.0 - "@opentelemetry/instrumentation": ^0.57.1 || ^0.200.0 - "@opentelemetry/sdk-trace-base": ^1.30.1 || ^2.0.0 - "@opentelemetry/semantic-conventions": ^1.30.0 - checksum: 10c0/f003000d79583310b67daa55e2704436da24b3fd1b690fecc93241fd6a358c765e1f1f2add8d955df53255068f1c3be267727496c0d611ee67acfb4789bbe588 - languageName: node - linkType: hard - -"@sentry/profiling-node@npm:^9.3.0": - version: 9.22.0 - resolution: "@sentry/profiling-node@npm:9.22.0" - dependencies: - "@sentry-internal/node-cpu-profiler": "npm:^2.2.0" - "@sentry/core": "npm:9.22.0" - "@sentry/node": "npm:9.22.0" - bin: - sentry-prune-profiler-binaries: scripts/prune-profiler-binaries.js - checksum: 10c0/ba96c0bc8a335f81a88769507f38d8e95514f50a0434cbe79716da636f7fd563ad2163cd6a10d6f146eacd35b4a214ef263d433890f099628eb02625a25633bf - languageName: node - linkType: hard - -"@types/connect@npm:3.4.38": - version: 3.4.38 - resolution: "@types/connect@npm:3.4.38" - dependencies: - "@types/node": "npm:*" - checksum: 10c0/2e1cdba2c410f25649e77856505cd60223250fa12dff7a503e492208dbfdd25f62859918f28aba95315251fd1f5e1ffbfca1e25e73037189ab85dd3f8d0a148c - languageName: node - linkType: hard - -"@types/deno@npm:^2.2.0": - version: 2.3.0 - resolution: "@types/deno@npm:2.3.0" - checksum: 10c0/7b4c9a2f905f1e737dcafffc8475575bd1647cbc3da140d71965f9a3289e34b6f3f2dc71c1e28f664aba6e999c0e9499d522329f734822bc4b11dd2c4f6342bc - languageName: node - linkType: hard - -"@types/diff-match-patch@npm:^1.0.36": - version: 1.0.36 - resolution: "@types/diff-match-patch@npm:1.0.36" - checksum: 10c0/0bad011ab138baa8bde94e7815064bb881f010452463272644ddbbb0590659cb93f7aa2776ff442c6721d70f202839e1053f8aa62d801cc4166f7a3ea9130055 - languageName: node - linkType: hard - -"@types/estree@npm:1.0.7, @types/estree@npm:^1.0.0": - version: 1.0.7 - resolution: "@types/estree@npm:1.0.7" - checksum: 10c0/be815254316882f7c40847336cd484c3bc1c3e34f710d197160d455dc9d6d050ffbf4c3bc76585dba86f737f020ab20bdb137ebe0e9116b0c86c7c0342221b8c - languageName: node - linkType: hard - -"@types/invariant@npm:^2": - version: 2.2.37 - resolution: "@types/invariant@npm:2.2.37" - checksum: 10c0/f57ed8445036ebda8bc93804f088c2a13050bbeef4e4bc6ed531a70e2869250dbe59413f2a9ed7d8f3efa960f191e8dfca9d25414d63cbf604d348428f8c5b75 - languageName: node - linkType: hard - -"@types/mysql@npm:2.15.26": - version: 2.15.26 - resolution: "@types/mysql@npm:2.15.26" - dependencies: - "@types/node": "npm:*" - checksum: 10c0/3cf279e7db05d56c0544532a4380b9079f579092379a04c8138bd5cf88dda5b31208ac2d23ce7dbf4e3a3f43aaeed44e72f9f19f726518f308efe95a7435619a - languageName: node - linkType: hard - -"@types/node@npm:*, @types/node@npm:^22.13.9": - version: 22.15.23 - resolution: "@types/node@npm:22.15.23" - dependencies: - undici-types: "npm:~6.21.0" - checksum: 10c0/e3ae0629dfb4357dad2a7838c481656abf089d852d83f0d0f14368f03ad21ce276cbecfdf62be2276ef39920db6b114e5bc8d87c37714bbab9aefb0ce1eb1473 - languageName: node - linkType: hard - -"@types/pg-pool@npm:2.0.6": - version: 2.0.6 - resolution: "@types/pg-pool@npm:2.0.6" - dependencies: - "@types/pg": "npm:*" - checksum: 10c0/41965d4d0b677c54ce45d36add760e496d356b78019cb062d124af40287cf6b0fd4d86e3b0085f443856c185983a60c8b0795ff76d15683e2a93c62f5ac0125f - languageName: node - linkType: hard - -"@types/pg@npm:*": - version: 8.15.2 - resolution: "@types/pg@npm:8.15.2" - dependencies: - "@types/node": "npm:*" - pg-protocol: "npm:*" - pg-types: "npm:^4.0.1" - checksum: 10c0/e3bc75f02af897ed960e83d1af9bd0cba1ff41cd0cbae0eaee323eae84f55e6d433f620aa1c72f7bd5107c80b018185c0e47de553cfc5439514c3da98768ef6c - languageName: node - linkType: hard - -"@types/pg@npm:8.6.1": - version: 8.6.1 - resolution: "@types/pg@npm:8.6.1" - dependencies: - "@types/node": "npm:*" - pg-protocol: "npm:*" - pg-types: "npm:^2.2.0" - checksum: 10c0/8d16660c9a4f050d6d5e391c59f9a62e9d377a2a6a7eb5865f8828082dbdfeab700fd707e585f42d67b29e796b32863aea5bd6d5cbb8ceda2d598da5d0c61693 - languageName: node - linkType: hard - -"@types/retry@npm:0.12.2": - version: 0.12.2 - resolution: "@types/retry@npm:0.12.2" - checksum: 10c0/07481551a988cc90b423351919928b9ddcd14e3f5591cac3ab950851bb20646e55a10e89141b38bc3093d2056d4df73700b22ff2612976ac86a6367862381884 - languageName: node - linkType: hard - -"@types/shimmer@npm:^1.2.0": - version: 1.2.0 - resolution: "@types/shimmer@npm:1.2.0" - checksum: 10c0/6f7bfe1b55601cfc3ae713fc74a03341f3834253b8b91cb2add926d5949e4a63f7e666f59c2a6e40a883a5f9e2f3e3af10f9d3aed9b60fced0bda87659e58d8d - languageName: node - linkType: hard - -"@types/tedious@npm:^4.0.14": - version: 4.0.14 - resolution: "@types/tedious@npm:4.0.14" - dependencies: - "@types/node": "npm:*" - checksum: 10c0/d2914f8e9b5b998e4275ec5f0130cba1c2fb47e75616b5c125a65ef6c1db2f1dc3f978c7900693856a15d72bbb4f4e94f805537a4ecb6dc126c64415d31c0590 - languageName: node - linkType: hard - -"@vitest/expect@npm:3.1.4": - version: 3.1.4 - resolution: "@vitest/expect@npm:3.1.4" - dependencies: - "@vitest/spy": "npm:3.1.4" - "@vitest/utils": "npm:3.1.4" - chai: "npm:^5.2.0" - tinyrainbow: "npm:^2.0.0" - checksum: 10c0/9cfd7eb6d965a179b4ec0610a9c08b14dc97dbaf81925c8209a054f7a2a3d1eef59fa5e5cd4dd9bf8cb940d85aee5f5102555511a94be9933faf4cc734462a16 - languageName: node - linkType: hard - -"@vitest/mocker@npm:3.1.4": - version: 3.1.4 - resolution: "@vitest/mocker@npm:3.1.4" - dependencies: - "@vitest/spy": "npm:3.1.4" - estree-walker: "npm:^3.0.3" - magic-string: "npm:^0.30.17" - peerDependencies: - msw: ^2.4.9 - vite: ^5.0.0 || ^6.0.0 - peerDependenciesMeta: - msw: - optional: true - vite: - optional: true - checksum: 10c0/d0b89e3974830d3893e7b8324a77ffeb9436db0969b57c01e2508ebd5b374c9d01f73796c8df8f555a3b1e1b502d40e725f159cd85966eebd3145b2f52e605e2 - languageName: node - linkType: hard - -"@vitest/pretty-format@npm:3.1.4, @vitest/pretty-format@npm:^3.1.4": - version: 3.1.4 - resolution: "@vitest/pretty-format@npm:3.1.4" - dependencies: - tinyrainbow: "npm:^2.0.0" - checksum: 10c0/11e133640435822b8b8528be540b3d66c1de27ebc2dcf1de87608b7f01a44d15302c4d4bf8330fa848a435450d88a09d7e9442747a5739ae5f500ccdd1493159 - languageName: node - linkType: hard - -"@vitest/runner@npm:3.1.4": - version: 3.1.4 - resolution: "@vitest/runner@npm:3.1.4" - dependencies: - "@vitest/utils": "npm:3.1.4" - pathe: "npm:^2.0.3" - checksum: 10c0/efb7512eebd3d786baa617eab332ec9ca6ce62eb1c9dd3945019f7510d745b3cd0fc2978868d792050905aacbf158eefc132359c83e61f0398b46be566013ee6 - languageName: node - linkType: hard - -"@vitest/snapshot@npm:3.1.4": - version: 3.1.4 - resolution: "@vitest/snapshot@npm:3.1.4" - dependencies: - "@vitest/pretty-format": "npm:3.1.4" - magic-string: "npm:^0.30.17" - pathe: "npm:^2.0.3" - checksum: 10c0/ce9d51e1b03e4f91ffad160c570991a8a3c603cb7dc2a9020e58c012e62dccbe2c6ee45e1a1d8489e265b4485c6721eb73b5e91404d1c76da08dcd663f4e18d1 - languageName: node - linkType: hard - -"@vitest/spy@npm:3.1.4": - version: 3.1.4 - resolution: "@vitest/spy@npm:3.1.4" - dependencies: - tinyspy: "npm:^3.0.2" - checksum: 10c0/747914ac18efa82d75349b0fb0ad8a5e2af6e04f5bbb50a980c9270dd8958f9ddf84cee0849a54e1645af088fc1f709add94a35e99cb14aca2cdb322622ba501 - languageName: node - linkType: hard - -"@vitest/utils@npm:3.1.4": - version: 3.1.4 - resolution: "@vitest/utils@npm:3.1.4" - dependencies: - "@vitest/pretty-format": "npm:3.1.4" - loupe: "npm:^3.1.3" - tinyrainbow: "npm:^2.0.0" - checksum: 10c0/78f1691a2dd578862b236f4962815e7475e547f006e7303a149dc5f910cc1ce6e0bdcbd7b4fd618122d62ca2dcc28bae464d31543f3898f5d88fa35017e00a95 - languageName: node - linkType: hard - -"abbrev@npm:^3.0.0": - version: 3.0.1 - resolution: "abbrev@npm:3.0.1" - checksum: 10c0/21ba8f574ea57a3106d6d35623f2c4a9111d9ee3e9a5be47baed46ec2457d2eac46e07a5c4a60186f88cb98abbe3e24f2d4cca70bc2b12f1692523e2209a9ccf - languageName: node - linkType: hard - -"acorn-import-attributes@npm:^1.9.5": - version: 1.9.5 - resolution: "acorn-import-attributes@npm:1.9.5" - peerDependencies: - acorn: ^8 - checksum: 10c0/5926eaaead2326d5a86f322ff1b617b0f698aa61dc719a5baa0e9d955c9885cc71febac3fb5bacff71bbf2c4f9c12db2056883c68c53eb962c048b952e1e013d - languageName: node - linkType: hard - -"acorn@npm:^8.14.0": - version: 8.14.1 - resolution: "acorn@npm:8.14.1" - bin: - acorn: bin/acorn - checksum: 10c0/dbd36c1ed1d2fa3550140000371fcf721578095b18777b85a79df231ca093b08edc6858d75d6e48c73e431c174dcf9214edbd7e6fa5911b93bd8abfa54e47123 - languageName: node - linkType: hard - -"actor-core@npm:0.9.0-rc.1": - version: 0.9.0-rc.1 - resolution: "actor-core@npm:0.9.0-rc.1" - dependencies: - "@hono/zod-openapi": "npm:^0.19.6" - cbor-x: "npm:^1.6.0" - hono: "npm:^4.7.0" - invariant: "npm:^2.2.4" - on-change: "npm:^5.0.1" - p-retry: "npm:^6.2.1" - zod: "npm:^3.24.1" - peerDependencies: - eventsource: ^3.0.5 - ws: ^8.0.0 - peerDependenciesMeta: - eventsource: - optional: true - ws: - optional: true - bin: - actor-core: ./dist/cli/mod.cjs - checksum: 10c0/07db1f0a783e53f25a7814da427203578748ca41ad5e35e648d071ad9e742dbe74eefd4f60e878aaa278de2e750def6f9b287d0942bed8928c8e7516bee06e18 - languageName: node - linkType: hard - -"agent-base@npm:^7.1.0, agent-base@npm:^7.1.2": - version: 7.1.3 - resolution: "agent-base@npm:7.1.3" - checksum: 10c0/6192b580c5b1d8fb399b9c62bf8343d76654c2dd62afcb9a52b2cf44a8b6ace1e3b704d3fe3547d91555c857d3df02603341ff2cb961b9cfe2b12f9f3c38ee11 - languageName: node - linkType: hard - -"ai@npm:^4.3.16": - version: 4.3.16 - resolution: "ai@npm:4.3.16" - dependencies: - "@ai-sdk/provider": "npm:1.1.3" - "@ai-sdk/provider-utils": "npm:2.2.8" - "@ai-sdk/react": "npm:1.2.12" - "@ai-sdk/ui-utils": "npm:1.2.11" - "@opentelemetry/api": "npm:1.9.0" - jsondiffpatch: "npm:0.6.0" - peerDependencies: - react: ^18 || ^19 || ^19.0.0-rc - zod: ^3.23.8 - peerDependenciesMeta: - react: - optional: true - checksum: 10c0/befe761c9386cda6de33370a2590900352b444d81959255c624e2bfd40765f126d29269f0ef3e00bde07daf237004aa0b66d0b253664aa478c148e923ce78c41 - languageName: node - linkType: hard - -"ansi-regex@npm:^5.0.1": - version: 5.0.1 - resolution: "ansi-regex@npm:5.0.1" - checksum: 10c0/9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737 - languageName: node - linkType: hard - -"ansi-regex@npm:^6.0.1": - version: 6.1.0 - resolution: "ansi-regex@npm:6.1.0" - checksum: 10c0/a91daeddd54746338478eef88af3439a7edf30f8e23196e2d6ed182da9add559c601266dbef01c2efa46a958ad6f1f8b176799657616c702b5b02e799e7fd8dc - languageName: node - linkType: hard - -"ansi-styles@npm:^4.0.0": - version: 4.3.0 - resolution: "ansi-styles@npm:4.3.0" - dependencies: - color-convert: "npm:^2.0.1" - checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 - languageName: node - linkType: hard - -"ansi-styles@npm:^6.1.0": - version: 6.2.1 - resolution: "ansi-styles@npm:6.2.1" - checksum: 10c0/5d1ec38c123984bcedd996eac680d548f31828bd679a66db2bdf11844634dde55fec3efa9c6bb1d89056a5e79c1ac540c4c784d592ea1d25028a92227d2f2d5c - languageName: node - linkType: hard - -"assertion-error@npm:^2.0.1": - version: 2.0.1 - resolution: "assertion-error@npm:2.0.1" - checksum: 10c0/bbbcb117ac6480138f8c93cf7f535614282dea9dc828f540cdece85e3c665e8f78958b96afac52f29ff883c72638e6a87d469ecc9fe5bc902df03ed24a55dba8 - languageName: node - linkType: hard - -"balanced-match@npm:^1.0.0": - version: 1.0.2 - resolution: "balanced-match@npm:1.0.2" - checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee - languageName: node - linkType: hard - -"brace-expansion@npm:^2.0.1": - version: 2.0.1 - resolution: "brace-expansion@npm:2.0.1" - dependencies: - balanced-match: "npm:^1.0.0" - checksum: 10c0/b358f2fe060e2d7a87aa015979ecea07f3c37d4018f8d6deb5bd4c229ad3a0384fe6029bb76cd8be63c81e516ee52d1a0673edbe2023d53a5191732ae3c3e49f - languageName: node - linkType: hard - -"buffer-from@npm:^1.0.0": - version: 1.1.2 - resolution: "buffer-from@npm:1.1.2" - checksum: 10c0/124fff9d66d691a86d3b062eff4663fe437a9d9ee4b47b1b9e97f5a5d14f6d5399345db80f796827be7c95e70a8e765dd404b7c3ff3b3324f98e9b0c8826cc34 - languageName: node - linkType: hard - -"bundle-name@npm:^4.1.0": - version: 4.1.0 - resolution: "bundle-name@npm:4.1.0" - dependencies: - run-applescript: "npm:^7.0.0" - checksum: 10c0/8e575981e79c2bcf14d8b1c027a3775c095d362d1382312f444a7c861b0e21513c0bd8db5bd2b16e50ba0709fa622d4eab6b53192d222120305e68359daece29 - languageName: node - linkType: hard - -"bundle-require@npm:^5.1.0": - version: 5.1.0 - resolution: "bundle-require@npm:5.1.0" - dependencies: - load-tsconfig: "npm:^0.2.3" - peerDependencies: - esbuild: ">=0.18" - checksum: 10c0/8bff9df68eb686f05af952003c78e70ffed2817968f92aebb2af620cc0b7428c8154df761d28f1b38508532204278950624ef86ce63644013dc57660a9d1810f - languageName: node - linkType: hard - -"cac@npm:^6.7.14": - version: 6.7.14 - resolution: "cac@npm:6.7.14" - checksum: 10c0/4ee06aaa7bab8981f0d54e5f5f9d4adcd64058e9697563ce336d8a3878ed018ee18ebe5359b2430eceae87e0758e62ea2019c3f52ae6e211b1bd2e133856cd10 - languageName: node - linkType: hard - -"cacache@npm:^19.0.1": - version: 19.0.1 - resolution: "cacache@npm:19.0.1" - dependencies: - "@npmcli/fs": "npm:^4.0.0" - fs-minipass: "npm:^3.0.0" - glob: "npm:^10.2.2" - lru-cache: "npm:^10.0.1" - minipass: "npm:^7.0.3" - minipass-collect: "npm:^2.0.1" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.4" - p-map: "npm:^7.0.2" - ssri: "npm:^12.0.0" - tar: "npm:^7.4.3" - unique-filename: "npm:^4.0.0" - checksum: 10c0/01f2134e1bd7d3ab68be851df96c8d63b492b1853b67f2eecb2c37bb682d37cb70bb858a16f2f0554d3c0071be6dfe21456a1ff6fa4b7eed996570d6a25ffe9c - languageName: node - linkType: hard - -"cbor-extract@npm:^2.2.0": - version: 2.2.0 - resolution: "cbor-extract@npm:2.2.0" - dependencies: - "@cbor-extract/cbor-extract-darwin-arm64": "npm:2.2.0" - "@cbor-extract/cbor-extract-darwin-x64": "npm:2.2.0" - "@cbor-extract/cbor-extract-linux-arm": "npm:2.2.0" - "@cbor-extract/cbor-extract-linux-arm64": "npm:2.2.0" - "@cbor-extract/cbor-extract-linux-x64": "npm:2.2.0" - "@cbor-extract/cbor-extract-win32-x64": "npm:2.2.0" - node-gyp: "npm:latest" - node-gyp-build-optional-packages: "npm:5.1.1" - dependenciesMeta: - "@cbor-extract/cbor-extract-darwin-arm64": - optional: true - "@cbor-extract/cbor-extract-darwin-x64": - optional: true - "@cbor-extract/cbor-extract-linux-arm": - optional: true - "@cbor-extract/cbor-extract-linux-arm64": - optional: true - "@cbor-extract/cbor-extract-linux-x64": - optional: true - "@cbor-extract/cbor-extract-win32-x64": - optional: true - bin: - download-cbor-prebuilds: bin/download-prebuilds.js - checksum: 10c0/c36dec273f2114fcfe3b544d03d8bfddd2d537d114b9f94ba52a9366a8b852ea9725850e3d29ceda5df6894faeb37026e3bf2cb0d2bb4429f0a699fcfdfa1b8b - languageName: node - linkType: hard - -"cbor-x@npm:^1.6.0": - version: 1.6.0 - resolution: "cbor-x@npm:1.6.0" - dependencies: - cbor-extract: "npm:^2.2.0" - dependenciesMeta: - cbor-extract: - optional: true - checksum: 10c0/c6ab391e935a60c8a768080806f2c9aee01b2b124de68997e3e4cb700753757286860186094a92f510b595d7f8c77b3023d9125a05247afcbfea08cae45a0615 - languageName: node - linkType: hard - -"chai@npm:^5.2.0": - version: 5.2.0 - resolution: "chai@npm:5.2.0" - dependencies: - assertion-error: "npm:^2.0.1" - check-error: "npm:^2.1.1" - deep-eql: "npm:^5.0.1" - loupe: "npm:^3.1.0" - pathval: "npm:^2.0.0" - checksum: 10c0/dfd1cb719c7cebb051b727672d382a35338af1470065cb12adb01f4ee451bbf528e0e0f9ab2016af5fc1eea4df6e7f4504dc8443f8f00bd8fb87ad32dc516f7d - languageName: node - linkType: hard - -"chalk@npm:^5.3.0": - version: 5.4.1 - resolution: "chalk@npm:5.4.1" - checksum: 10c0/b23e88132c702f4855ca6d25cb5538b1114343e41472d5263ee8a37cccfccd9c4216d111e1097c6a27830407a1dc81fecdf2a56f2c63033d4dbbd88c10b0dcef - languageName: node - linkType: hard - -"check-error@npm:^2.1.1": - version: 2.1.1 - resolution: "check-error@npm:2.1.1" - checksum: 10c0/979f13eccab306cf1785fa10941a590b4e7ea9916ea2a4f8c87f0316fc3eab07eabefb6e587424ef0f88cbcd3805791f172ea739863ca3d7ce2afc54641c7f0e - languageName: node - linkType: hard - -"chokidar@npm:^4.0.3": - version: 4.0.3 - resolution: "chokidar@npm:4.0.3" - dependencies: - readdirp: "npm:^4.0.1" - checksum: 10c0/a58b9df05bb452f7d105d9e7229ac82fa873741c0c40ddcc7bb82f8a909fbe3f7814c9ebe9bc9a2bef9b737c0ec6e2d699d179048ef06ad3ec46315df0ebe6ad - languageName: node - linkType: hard - -"chownr@npm:^3.0.0": - version: 3.0.0 - resolution: "chownr@npm:3.0.0" - checksum: 10c0/43925b87700f7e3893296c8e9c56cc58f926411cce3a6e5898136daaf08f08b9a8eb76d37d3267e707d0dcc17aed2e2ebdf5848c0c3ce95cf910a919935c1b10 - languageName: node - linkType: hard - -"cjs-module-lexer@npm:^1.2.2": - version: 1.4.3 - resolution: "cjs-module-lexer@npm:1.4.3" - checksum: 10c0/076b3af85adc4d65dbdab1b5b240fe5b45d44fcf0ef9d429044dd94d19be5589376805c44fb2d4b3e684e5fe6a9b7cf3e426476a6507c45283c5fc6ff95240be - languageName: node - linkType: hard - -"color-convert@npm:^2.0.1": - version: 2.0.1 - resolution: "color-convert@npm:2.0.1" - dependencies: - color-name: "npm:~1.1.4" - checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 - languageName: node - linkType: hard - -"color-name@npm:~1.1.4": - version: 1.1.4 - resolution: "color-name@npm:1.1.4" - checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 - languageName: node - linkType: hard - -"cross-spawn@npm:^7.0.6": - version: 7.0.6 - resolution: "cross-spawn@npm:7.0.6" - dependencies: - path-key: "npm:^3.1.0" - shebang-command: "npm:^2.0.0" - which: "npm:^2.0.1" - checksum: 10c0/053ea8b2135caff68a9e81470e845613e374e7309a47731e81639de3eaeb90c3d01af0e0b44d2ab9d50b43467223b88567dfeb3262db942dc063b9976718ffc1 - languageName: node - linkType: hard - -"debug@npm:4, debug@npm:^4.3.4, debug@npm:^4.3.5, debug@npm:^4.4.0": - version: 4.4.1 - resolution: "debug@npm:4.4.1" - dependencies: - ms: "npm:^2.1.3" - peerDependenciesMeta: - supports-color: - optional: true - checksum: 10c0/d2b44bc1afd912b49bb7ebb0d50a860dc93a4dd7d946e8de94abc957bb63726b7dd5aa48c18c2386c379ec024c46692e15ed3ed97d481729f929201e671fcd55 - languageName: node - linkType: hard - -"deep-eql@npm:^5.0.1": - version: 5.0.2 - resolution: "deep-eql@npm:5.0.2" - checksum: 10c0/7102cf3b7bb719c6b9c0db2e19bf0aa9318d141581befe8c7ce8ccd39af9eaa4346e5e05adef7f9bd7015da0f13a3a25dcfe306ef79dc8668aedbecb658dd247 - languageName: node - linkType: hard - -"default-browser-id@npm:^5.0.0": - version: 5.0.0 - resolution: "default-browser-id@npm:5.0.0" - checksum: 10c0/957fb886502594c8e645e812dfe93dba30ed82e8460d20ce39c53c5b0f3e2afb6ceaec2249083b90bdfbb4cb0f34e1f73fde3d68cac00becdbcfd894156b5ead - languageName: node - linkType: hard - -"default-browser@npm:^5.2.1": - version: 5.2.1 - resolution: "default-browser@npm:5.2.1" - dependencies: - bundle-name: "npm:^4.1.0" - default-browser-id: "npm:^5.0.0" - checksum: 10c0/73f17dc3c58026c55bb5538749597db31f9561c0193cd98604144b704a981c95a466f8ecc3c2db63d8bfd04fb0d426904834cfc91ae510c6aeb97e13c5167c4d - languageName: node - linkType: hard - -"define-lazy-prop@npm:^3.0.0": - version: 3.0.0 - resolution: "define-lazy-prop@npm:3.0.0" - checksum: 10c0/5ab0b2bf3fa58b3a443140bbd4cd3db1f91b985cc8a246d330b9ac3fc0b6a325a6d82bddc0b055123d745b3f9931afeea74a5ec545439a1630b9c8512b0eeb49 - languageName: node - linkType: hard - -"dequal@npm:^2.0.3": - version: 2.0.3 - resolution: "dequal@npm:2.0.3" - checksum: 10c0/f98860cdf58b64991ae10205137c0e97d384c3a4edc7f807603887b7c4b850af1224a33d88012009f150861cbee4fa2d322c4cc04b9313bee312e47f6ecaa888 - languageName: node - linkType: hard - -"detect-libc@npm:^2.0.1, detect-libc@npm:^2.0.3": - version: 2.0.4 - resolution: "detect-libc@npm:2.0.4" - checksum: 10c0/c15541f836eba4b1f521e4eecc28eefefdbc10a94d3b8cb4c507689f332cc111babb95deda66f2de050b22122113189986d5190be97d51b5a2b23b938415e67c - languageName: node - linkType: hard - -"diff-match-patch@npm:^1.0.5": - version: 1.0.5 - resolution: "diff-match-patch@npm:1.0.5" - checksum: 10c0/142b6fad627b9ef309d11bd935e82b84c814165a02500f046e2773f4ea894d10ed3017ac20454900d79d4a0322079f5b713cf0986aaf15fce0ec4a2479980c86 - languageName: node - linkType: hard - -"dotenv@npm:^16.5.0": - version: 16.5.0 - resolution: "dotenv@npm:16.5.0" - checksum: 10c0/5bc94c919fbd955bf0ba44d33922a1e93d1078e64a1db5c30faeded1d996e7a83c55332cb8ea4fae5a9ca4d0be44cbceb95c5811e70f9f095298df09d1997dd9 - languageName: node - linkType: hard - -"eastasianwidth@npm:^0.2.0": - version: 0.2.0 - resolution: "eastasianwidth@npm:0.2.0" - checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 - languageName: node - linkType: hard - -"emoji-regex@npm:^8.0.0": - version: 8.0.0 - resolution: "emoji-regex@npm:8.0.0" - checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 - languageName: node - linkType: hard - -"emoji-regex@npm:^9.2.2": - version: 9.2.2 - resolution: "emoji-regex@npm:9.2.2" - checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 - languageName: node - linkType: hard - -"encoding@npm:^0.1.13": - version: 0.1.13 - resolution: "encoding@npm:0.1.13" - dependencies: - iconv-lite: "npm:^0.6.2" - checksum: 10c0/36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039 - languageName: node - linkType: hard - -"env-paths@npm:^2.2.0": - version: 2.2.1 - resolution: "env-paths@npm:2.2.1" - checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 - languageName: node - linkType: hard - -"err-code@npm:^2.0.2": - version: 2.0.3 - resolution: "err-code@npm:2.0.3" - checksum: 10c0/b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66 - languageName: node - linkType: hard - -"es-module-lexer@npm:^1.7.0": - version: 1.7.0 - resolution: "es-module-lexer@npm:1.7.0" - checksum: 10c0/4c935affcbfeba7fb4533e1da10fa8568043df1e3574b869385980de9e2d475ddc36769891936dbb07036edb3c3786a8b78ccf44964cd130dedc1f2c984b6c7b - languageName: node - linkType: hard - -"esbuild@npm:^0.25.0, esbuild@npm:^0.25.1": - version: 0.25.5 - resolution: "esbuild@npm:0.25.5" - dependencies: - "@esbuild/aix-ppc64": "npm:0.25.5" - "@esbuild/android-arm": "npm:0.25.5" - "@esbuild/android-arm64": "npm:0.25.5" - "@esbuild/android-x64": "npm:0.25.5" - "@esbuild/darwin-arm64": "npm:0.25.5" - "@esbuild/darwin-x64": "npm:0.25.5" - "@esbuild/freebsd-arm64": "npm:0.25.5" - "@esbuild/freebsd-x64": "npm:0.25.5" - "@esbuild/linux-arm": "npm:0.25.5" - "@esbuild/linux-arm64": "npm:0.25.5" - "@esbuild/linux-ia32": "npm:0.25.5" - "@esbuild/linux-loong64": "npm:0.25.5" - "@esbuild/linux-mips64el": "npm:0.25.5" - "@esbuild/linux-ppc64": "npm:0.25.5" - "@esbuild/linux-riscv64": "npm:0.25.5" - "@esbuild/linux-s390x": "npm:0.25.5" - "@esbuild/linux-x64": "npm:0.25.5" - "@esbuild/netbsd-arm64": "npm:0.25.5" - "@esbuild/netbsd-x64": "npm:0.25.5" - "@esbuild/openbsd-arm64": "npm:0.25.5" - "@esbuild/openbsd-x64": "npm:0.25.5" - "@esbuild/sunos-x64": "npm:0.25.5" - "@esbuild/win32-arm64": "npm:0.25.5" - "@esbuild/win32-ia32": "npm:0.25.5" - "@esbuild/win32-x64": "npm:0.25.5" - dependenciesMeta: - "@esbuild/aix-ppc64": - optional: true - "@esbuild/android-arm": - optional: true - "@esbuild/android-arm64": - optional: true - "@esbuild/android-x64": - optional: true - "@esbuild/darwin-arm64": - optional: true - "@esbuild/darwin-x64": - optional: true - "@esbuild/freebsd-arm64": - optional: true - "@esbuild/freebsd-x64": - optional: true - "@esbuild/linux-arm": - optional: true - "@esbuild/linux-arm64": - optional: true - "@esbuild/linux-ia32": - optional: true - "@esbuild/linux-loong64": - optional: true - "@esbuild/linux-mips64el": - optional: true - "@esbuild/linux-ppc64": - optional: true - "@esbuild/linux-riscv64": - optional: true - "@esbuild/linux-s390x": - optional: true - "@esbuild/linux-x64": - optional: true - "@esbuild/netbsd-arm64": - optional: true - "@esbuild/netbsd-x64": - optional: true - "@esbuild/openbsd-arm64": - optional: true - "@esbuild/openbsd-x64": - optional: true - "@esbuild/sunos-x64": - optional: true - "@esbuild/win32-arm64": - optional: true - "@esbuild/win32-ia32": - optional: true - "@esbuild/win32-x64": - optional: true - bin: - esbuild: bin/esbuild - checksum: 10c0/aba8cbc11927fa77562722ed5e95541ce2853f67ad7bdc40382b558abc2e0ec57d92ffb820f082ba2047b4ef9f3bc3da068cdebe30dfd3850cfa3827a78d604e - languageName: node - linkType: hard - -"esbuild@npm:~0.18.20": - version: 0.18.20 - resolution: "esbuild@npm:0.18.20" - dependencies: - "@esbuild/android-arm": "npm:0.18.20" - "@esbuild/android-arm64": "npm:0.18.20" - "@esbuild/android-x64": "npm:0.18.20" - "@esbuild/darwin-arm64": "npm:0.18.20" - "@esbuild/darwin-x64": "npm:0.18.20" - "@esbuild/freebsd-arm64": "npm:0.18.20" - "@esbuild/freebsd-x64": "npm:0.18.20" - "@esbuild/linux-arm": "npm:0.18.20" - "@esbuild/linux-arm64": "npm:0.18.20" - "@esbuild/linux-ia32": "npm:0.18.20" - "@esbuild/linux-loong64": "npm:0.18.20" - "@esbuild/linux-mips64el": "npm:0.18.20" - "@esbuild/linux-ppc64": "npm:0.18.20" - "@esbuild/linux-riscv64": "npm:0.18.20" - "@esbuild/linux-s390x": "npm:0.18.20" - "@esbuild/linux-x64": "npm:0.18.20" - "@esbuild/netbsd-x64": "npm:0.18.20" - "@esbuild/openbsd-x64": "npm:0.18.20" - "@esbuild/sunos-x64": "npm:0.18.20" - "@esbuild/win32-arm64": "npm:0.18.20" - "@esbuild/win32-ia32": "npm:0.18.20" - "@esbuild/win32-x64": "npm:0.18.20" - dependenciesMeta: - "@esbuild/android-arm": - optional: true - "@esbuild/android-arm64": - optional: true - "@esbuild/android-x64": - optional: true - "@esbuild/darwin-arm64": - optional: true - "@esbuild/darwin-x64": - optional: true - "@esbuild/freebsd-arm64": - optional: true - "@esbuild/freebsd-x64": - optional: true - "@esbuild/linux-arm": - optional: true - "@esbuild/linux-arm64": - optional: true - "@esbuild/linux-ia32": - optional: true - "@esbuild/linux-loong64": - optional: true - "@esbuild/linux-mips64el": - optional: true - "@esbuild/linux-ppc64": - optional: true - "@esbuild/linux-riscv64": - optional: true - "@esbuild/linux-s390x": - optional: true - "@esbuild/linux-x64": - optional: true - "@esbuild/netbsd-x64": - optional: true - "@esbuild/openbsd-x64": - optional: true - "@esbuild/sunos-x64": - optional: true - "@esbuild/win32-arm64": - optional: true - "@esbuild/win32-ia32": - optional: true - "@esbuild/win32-x64": - optional: true - bin: - esbuild: bin/esbuild - checksum: 10c0/473b1d92842f50a303cf948a11ebd5f69581cd254d599dd9d62f9989858e0533f64e83b723b5e1398a5b488c0f5fd088795b4235f65ecaf4f007d4b79f04bc88 - languageName: node - linkType: hard - -"estree-walker@npm:^3.0.3": - version: 3.0.3 - resolution: "estree-walker@npm:3.0.3" - dependencies: - "@types/estree": "npm:^1.0.0" - checksum: 10c0/c12e3c2b2642d2bcae7d5aa495c60fa2f299160946535763969a1c83fc74518ffa9c2cd3a8b69ac56aea547df6a8aac25f729a342992ef0bbac5f1c73e78995d - languageName: node - linkType: hard - -"expect-type@npm:^1.2.1": - version: 1.2.1 - resolution: "expect-type@npm:1.2.1" - checksum: 10c0/b775c9adab3c190dd0d398c722531726cdd6022849b4adba19dceab58dda7e000a7c6c872408cd73d665baa20d381eca36af4f7b393a4ba60dd10232d1fb8898 - languageName: node - linkType: hard - -"exponential-backoff@npm:^3.1.1": - version: 3.1.2 - resolution: "exponential-backoff@npm:3.1.2" - checksum: 10c0/d9d3e1eafa21b78464297df91f1776f7fbaa3d5e3f7f0995648ca5b89c069d17055033817348d9f4a43d1c20b0eab84f75af6991751e839df53e4dfd6f22e844 - languageName: node - linkType: hard - -"fdir@npm:^6.4.4": - version: 6.4.5 - resolution: "fdir@npm:6.4.5" - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - checksum: 10c0/5d63330a1b97165e9b0fb20369fafc7cf826bc4b3e374efcb650bc77d7145ac01193b5da1a7591eab89ae6fd6b15cdd414085910b2a2b42296b1480c9f2677af - languageName: node - linkType: hard - -"foreground-child@npm:^3.1.0": - version: 3.3.1 - resolution: "foreground-child@npm:3.3.1" - dependencies: - cross-spawn: "npm:^7.0.6" - signal-exit: "npm:^4.0.1" - checksum: 10c0/8986e4af2430896e65bc2788d6679067294d6aee9545daefc84923a0a4b399ad9c7a3ea7bd8c0b2b80fdf4a92de4c69df3f628233ff3224260e9c1541a9e9ed3 - languageName: node - linkType: hard - -"forwarded-parse@npm:2.1.2": - version: 2.1.2 - resolution: "forwarded-parse@npm:2.1.2" - checksum: 10c0/0c6b4c631775f272b4475e935108635495e8a5b261d1b4a5caef31c47c5a0b04134adc564e655aadfef366a02647fa3ae90a1d3ac19929f3ade47f9bed53036a - languageName: node - linkType: hard - -"fs-minipass@npm:^3.0.0": - version: 3.0.3 - resolution: "fs-minipass@npm:3.0.3" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94 - languageName: node - linkType: hard - -"fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": - version: 2.3.3 - resolution: "fsevents@npm:2.3.3" - dependencies: - node-gyp: "npm:latest" - checksum: 10c0/a1f0c44595123ed717febbc478aa952e47adfc28e2092be66b8ab1635147254ca6cfe1df792a8997f22716d4cbafc73309899ff7bfac2ac3ad8cf2e4ecc3ec60 - conditions: os=darwin - languageName: node - linkType: hard - -"fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": - version: 2.3.3 - resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" - dependencies: - node-gyp: "npm:latest" - conditions: os=darwin - languageName: node - linkType: hard - -"function-bind@npm:^1.1.2": - version: 1.1.2 - resolution: "function-bind@npm:1.1.2" - checksum: 10c0/d8680ee1e5fcd4c197e4ac33b2b4dce03c71f4d91717292785703db200f5c21f977c568d28061226f9b5900cbcd2c84463646134fd5337e7925e0942bc3f46d5 - languageName: node - linkType: hard - -"get-tsconfig@npm:^4.7.2": - version: 4.10.1 - resolution: "get-tsconfig@npm:4.10.1" - dependencies: - resolve-pkg-maps: "npm:^1.0.0" - checksum: 10c0/7f8e3dabc6a49b747920a800fb88e1952fef871cdf51b79e98db48275a5de6cdaf499c55ee67df5fa6fe7ce65f0063e26de0f2e53049b408c585aa74d39ffa21 - languageName: node - linkType: hard - -"glob@npm:^10.2.2": - version: 10.4.5 - resolution: "glob@npm:10.4.5" - dependencies: - foreground-child: "npm:^3.1.0" - jackspeak: "npm:^3.1.2" - minimatch: "npm:^9.0.4" - minipass: "npm:^7.1.2" - package-json-from-dist: "npm:^1.0.0" - path-scurry: "npm:^1.11.1" - bin: - glob: dist/esm/bin.mjs - checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e - languageName: node - linkType: hard - -"graceful-fs@npm:^4.2.6": - version: 4.2.11 - resolution: "graceful-fs@npm:4.2.11" - checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 - languageName: node - linkType: hard - -"graphql@npm:^15.4.0": - version: 15.10.1 - resolution: "graphql@npm:15.10.1" - checksum: 10c0/8bbf6c1acda84dcff532f2ec492ffb2859d2ffd0c8e0143447c727388c5c3d7cab338143ecbdf61acc1f04227f2e0a8180f26ce9ea280b63a65079c58f6cfa25 - languageName: node - linkType: hard - -"hasown@npm:^2.0.2": - version: 2.0.2 - resolution: "hasown@npm:2.0.2" - dependencies: - function-bind: "npm:^1.1.2" - checksum: 10c0/3769d434703b8ac66b209a4cca0737519925bbdb61dd887f93a16372b14694c63ff4e797686d87c90f08168e81082248b9b028bad60d4da9e0d1148766f56eb9 - languageName: node - linkType: hard - -"hono@npm:^4.7.0": - version: 4.7.10 - resolution: "hono@npm:4.7.10" - checksum: 10c0/985aadcccb323fee7012f7c38e58b85332b1370a5ae69649ed29ae538a57cd4233f6198c54cc1fe3716b6b9ab20f8c7518d71027d7c46003c2d2ce982ce37c48 - languageName: node - linkType: hard - -"http-cache-semantics@npm:^4.1.1": - version: 4.2.0 - resolution: "http-cache-semantics@npm:4.2.0" - checksum: 10c0/45b66a945cf13ec2d1f29432277201313babf4a01d9e52f44b31ca923434083afeca03f18417f599c9ab3d0e7b618ceb21257542338b57c54b710463b4a53e37 - languageName: node - linkType: hard - -"http-proxy-agent@npm:^7.0.0": - version: 7.0.2 - resolution: "http-proxy-agent@npm:7.0.2" - dependencies: - agent-base: "npm:^7.1.0" - debug: "npm:^4.3.4" - checksum: 10c0/4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921 - languageName: node - linkType: hard - -"https-proxy-agent@npm:^7.0.1": - version: 7.0.6 - resolution: "https-proxy-agent@npm:7.0.6" - dependencies: - agent-base: "npm:^7.1.2" - debug: "npm:4" - checksum: 10c0/f729219bc735edb621fa30e6e84e60ee5d00802b8247aac0d7b79b0bd6d4b3294737a337b93b86a0bd9e68099d031858a39260c976dc14cdbba238ba1f8779ac - languageName: node - linkType: hard - -"iconv-lite@npm:^0.6.2": - version: 0.6.3 - resolution: "iconv-lite@npm:0.6.3" - dependencies: - safer-buffer: "npm:>= 2.1.2 < 3.0.0" - checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 - languageName: node - linkType: hard - -"import-in-the-middle@npm:^1.13.1, import-in-the-middle@npm:^1.8.1": - version: 1.14.0 - resolution: "import-in-the-middle@npm:1.14.0" - dependencies: - acorn: "npm:^8.14.0" - acorn-import-attributes: "npm:^1.9.5" - cjs-module-lexer: "npm:^1.2.2" - module-details-from-path: "npm:^1.0.3" - checksum: 10c0/7df8bff5cf8f3dc98d9e49b6e83b39bc5571d6afbeeaa7f783829e6f4a201329595f51f7c037ee7db395bb3866625d056edcd3f112a93f0e1f31930dbd8ec437 - languageName: node - linkType: hard - -"imurmurhash@npm:^0.1.4": - version: 0.1.4 - resolution: "imurmurhash@npm:0.1.4" - checksum: 10c0/8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 - languageName: node - linkType: hard - -"invariant@npm:^2.2.4": - version: 2.2.4 - resolution: "invariant@npm:2.2.4" - dependencies: - loose-envify: "npm:^1.0.0" - checksum: 10c0/5af133a917c0bcf65e84e7f23e779e7abc1cd49cb7fdc62d00d1de74b0d8c1b5ee74ac7766099fb3be1b05b26dfc67bab76a17030d2fe7ea2eef867434362dfc - languageName: node - linkType: hard - -"ip-address@npm:^9.0.5": - version: 9.0.5 - resolution: "ip-address@npm:9.0.5" - dependencies: - jsbn: "npm:1.1.0" - sprintf-js: "npm:^1.1.3" - checksum: 10c0/331cd07fafcb3b24100613e4b53e1a2b4feab11e671e655d46dc09ee233da5011284d09ca40c4ecbdfe1d0004f462958675c224a804259f2f78d2465a87824bc - languageName: node - linkType: hard - -"is-core-module@npm:^2.16.0": - version: 2.16.1 - resolution: "is-core-module@npm:2.16.1" - dependencies: - hasown: "npm:^2.0.2" - checksum: 10c0/898443c14780a577e807618aaae2b6f745c8538eca5c7bc11388a3f2dc6de82b9902bcc7eb74f07be672b11bbe82dd6a6edded44a00cb3d8f933d0459905eedd - languageName: node - linkType: hard - -"is-docker@npm:^3.0.0": - version: 3.0.0 - resolution: "is-docker@npm:3.0.0" - bin: - is-docker: cli.js - checksum: 10c0/d2c4f8e6d3e34df75a5defd44991b6068afad4835bb783b902fa12d13ebdb8f41b2a199dcb0b5ed2cb78bfee9e4c0bbdb69c2d9646f4106464674d3e697a5856 - languageName: node - linkType: hard - -"is-fullwidth-code-point@npm:^3.0.0": - version: 3.0.0 - resolution: "is-fullwidth-code-point@npm:3.0.0" - checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc - languageName: node - linkType: hard - -"is-inside-container@npm:^1.0.0": - version: 1.0.0 - resolution: "is-inside-container@npm:1.0.0" - dependencies: - is-docker: "npm:^3.0.0" - bin: - is-inside-container: cli.js - checksum: 10c0/a8efb0e84f6197e6ff5c64c52890fa9acb49b7b74fed4da7c95383965da6f0fa592b4dbd5e38a79f87fc108196937acdbcd758fcefc9b140e479b39ce1fcd1cd - languageName: node - linkType: hard - -"is-network-error@npm:^1.0.0": - version: 1.1.0 - resolution: "is-network-error@npm:1.1.0" - checksum: 10c0/89eef83c2a4cf43d853145ce175d1cf43183b7a58d48c7a03e7eed4eb395d0934c1f6d101255cdd8c8c2980ab529bfbe5dd9edb24e1c3c28d2b3c814469b5b7d - languageName: node - linkType: hard - -"is-wsl@npm:^3.1.0": - version: 3.1.0 - resolution: "is-wsl@npm:3.1.0" - dependencies: - is-inside-container: "npm:^1.0.0" - checksum: 10c0/d3317c11995690a32c362100225e22ba793678fe8732660c6de511ae71a0ff05b06980cf21f98a6bf40d7be0e9e9506f859abe00a1118287d63e53d0a3d06947 - languageName: node - linkType: hard - -"isexe@npm:^2.0.0": - version: 2.0.0 - resolution: "isexe@npm:2.0.0" - checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d - languageName: node - linkType: hard - -"isexe@npm:^3.1.1": - version: 3.1.1 - resolution: "isexe@npm:3.1.1" - checksum: 10c0/9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7 - languageName: node - linkType: hard - -"isomorphic-unfetch@npm:^3.1.0": - version: 3.1.0 - resolution: "isomorphic-unfetch@npm:3.1.0" - dependencies: - node-fetch: "npm:^2.6.1" - unfetch: "npm:^4.2.0" - checksum: 10c0/d3b61fca06304db692b7f76bdfd3a00f410e42cfa7403c3b250546bf71589d18cf2f355922f57198e4cc4a9872d3647b20397a5c3edf1a347c90d57c83cf2a89 - languageName: node - linkType: hard - -"jackspeak@npm:^3.1.2": - version: 3.4.3 - resolution: "jackspeak@npm:3.4.3" - dependencies: - "@isaacs/cliui": "npm:^8.0.2" - "@pkgjs/parseargs": "npm:^0.11.0" - dependenciesMeta: - "@pkgjs/parseargs": - optional: true - checksum: 10c0/6acc10d139eaefdbe04d2f679e6191b3abf073f111edf10b1de5302c97ec93fffeb2fdd8681ed17f16268aa9dd4f8c588ed9d1d3bffbbfa6e8bf897cbb3149b9 - languageName: node - linkType: hard - -"jose@npm:^6.0.10": - version: 6.0.11 - resolution: "jose@npm:6.0.11" - checksum: 10c0/d290be4532174e7a53730b7fb84c74327531172bd403b196c592b312b73eedb7489949837bfe831fdbd280799bfc5ba778bc807495a73eda08ae6c49414f405a - languageName: node - linkType: hard - -"js-tokens@npm:^3.0.0 || ^4.0.0": - version: 4.0.0 - resolution: "js-tokens@npm:4.0.0" - checksum: 10c0/e248708d377aa058eacf2037b07ded847790e6de892bbad3dac0abba2e759cb9f121b00099a65195616badcb6eca8d14d975cb3e89eb1cfda644756402c8aeed - languageName: node - linkType: hard - -"jsbn@npm:1.1.0": - version: 1.1.0 - resolution: "jsbn@npm:1.1.0" - checksum: 10c0/4f907fb78d7b712e11dea8c165fe0921f81a657d3443dde75359ed52eb2b5d33ce6773d97985a089f09a65edd80b11cb75c767b57ba47391fee4c969f7215c96 - languageName: node - linkType: hard - -"json-schema@npm:^0.4.0": - version: 0.4.0 - resolution: "json-schema@npm:0.4.0" - checksum: 10c0/d4a637ec1d83544857c1c163232f3da46912e971d5bf054ba44fdb88f07d8d359a462b4aec46f2745efbc57053365608d88bc1d7b1729f7b4fc3369765639ed3 - languageName: node - linkType: hard - -"jsondiffpatch@npm:0.6.0": - version: 0.6.0 - resolution: "jsondiffpatch@npm:0.6.0" - dependencies: - "@types/diff-match-patch": "npm:^1.0.36" - chalk: "npm:^5.3.0" - diff-match-patch: "npm:^1.0.5" - bin: - jsondiffpatch: bin/jsondiffpatch.js - checksum: 10c0/f7822e48a8ef8b9f7c6024cc59b7d3707a9fe6d84fd776d169de5a1803ad551ffe7cfdc7587f3900f224bc70897355884ed43eb1c8ccd02e7f7b43a7ebcfed4f - languageName: node - linkType: hard - -"linear-agent-starter@workspace:.": - version: 0.0.0-use.local - resolution: "linear-agent-starter@workspace:." - dependencies: - "@actor-core/cli": "npm:0.9.0-rc.1" - "@actor-core/nodejs": "npm:0.9.0-rc.1" - "@actor-core/rivet": "npm:0.9.0-rc.1" - "@ai-sdk/anthropic": "npm:^1.2.12" - "@ai-sdk/openai": "npm:^1.3.22" - "@linear/sdk": "npm:^40.0.0" - "@types/deno": "npm:^2.2.0" - "@types/invariant": "npm:^2" - "@types/node": "npm:^22.13.9" - actor-core: "npm:0.9.0-rc.1" - ai: "npm:^4.3.16" - dotenv: "npm:^16.5.0" - hono: "npm:^4.7.0" - invariant: "npm:^2.2.4" - openid-client: "npm:^6.5.0" - tsx: "npm:^3.12.7" - typescript: "npm:^5.7.3" - vitest: "npm:^3.1.1" - languageName: unknown - linkType: soft - -"load-tsconfig@npm:^0.2.3": - version: 0.2.5 - resolution: "load-tsconfig@npm:0.2.5" - checksum: 10c0/bf2823dd26389d3497b6567f07435c5a7a58d9df82e879b0b3892f87d8db26900f84c85bc329ef41c0540c0d6a448d1c23ddc64a80f3ff6838b940f3915a3fcb - languageName: node - linkType: hard - -"loose-envify@npm:^1.0.0": - version: 1.4.0 - resolution: "loose-envify@npm:1.4.0" - dependencies: - js-tokens: "npm:^3.0.0 || ^4.0.0" - bin: - loose-envify: cli.js - checksum: 10c0/655d110220983c1a4b9c0c679a2e8016d4b67f6e9c7b5435ff5979ecdb20d0813f4dec0a08674fcbdd4846a3f07edbb50a36811fd37930b94aaa0d9daceb017e - languageName: node - linkType: hard - -"loupe@npm:^3.1.0, loupe@npm:^3.1.3": - version: 3.1.3 - resolution: "loupe@npm:3.1.3" - checksum: 10c0/f5dab4144254677de83a35285be1b8aba58b3861439ce4ba65875d0d5f3445a4a496daef63100ccf02b2dbc25bf58c6db84c9cb0b96d6435331e9d0a33b48541 - languageName: node - linkType: hard - -"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": - version: 10.4.3 - resolution: "lru-cache@npm:10.4.3" - checksum: 10c0/ebd04fbca961e6c1d6c0af3799adcc966a1babe798f685bb84e6599266599cd95d94630b10262f5424539bc4640107e8a33aa28585374abf561d30d16f4b39fb - languageName: node - linkType: hard - -"magic-string@npm:^0.30.17": - version: 0.30.17 - resolution: "magic-string@npm:0.30.17" - dependencies: - "@jridgewell/sourcemap-codec": "npm:^1.5.0" - checksum: 10c0/16826e415d04b88378f200fe022b53e638e3838b9e496edda6c0e086d7753a44a6ed187adc72d19f3623810589bf139af1a315541cd6a26ae0771a0193eaf7b8 - languageName: node - linkType: hard - -"make-fetch-happen@npm:^14.0.3": - version: 14.0.3 - resolution: "make-fetch-happen@npm:14.0.3" - dependencies: - "@npmcli/agent": "npm:^3.0.0" - cacache: "npm:^19.0.1" - http-cache-semantics: "npm:^4.1.1" - minipass: "npm:^7.0.2" - minipass-fetch: "npm:^4.0.0" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.4" - negotiator: "npm:^1.0.0" - proc-log: "npm:^5.0.0" - promise-retry: "npm:^2.0.1" - ssri: "npm:^12.0.0" - checksum: 10c0/c40efb5e5296e7feb8e37155bde8eb70bc57d731b1f7d90e35a092fde403d7697c56fb49334d92d330d6f1ca29a98142036d6480a12681133a0a1453164cb2f0 - languageName: node - linkType: hard - -"minimatch@npm:^9.0.0, minimatch@npm:^9.0.4": - version: 9.0.5 - resolution: "minimatch@npm:9.0.5" - dependencies: - brace-expansion: "npm:^2.0.1" - checksum: 10c0/de96cf5e35bdf0eab3e2c853522f98ffbe9a36c37797778d2665231ec1f20a9447a7e567cb640901f89e4daaa95ae5d70c65a9e8aa2bb0019b6facbc3c0575ed - languageName: node - linkType: hard - -"minipass-collect@npm:^2.0.1": - version: 2.0.1 - resolution: "minipass-collect@npm:2.0.1" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e - languageName: node - linkType: hard - -"minipass-fetch@npm:^4.0.0": - version: 4.0.1 - resolution: "minipass-fetch@npm:4.0.1" - dependencies: - encoding: "npm:^0.1.13" - minipass: "npm:^7.0.3" - minipass-sized: "npm:^1.0.3" - minizlib: "npm:^3.0.1" - dependenciesMeta: - encoding: - optional: true - checksum: 10c0/a3147b2efe8e078c9bf9d024a0059339c5a09c5b1dded6900a219c218cc8b1b78510b62dae556b507304af226b18c3f1aeb1d48660283602d5b6586c399eed5c - languageName: node - linkType: hard - -"minipass-flush@npm:^1.0.5": - version: 1.0.5 - resolution: "minipass-flush@npm:1.0.5" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/2a51b63feb799d2bb34669205eee7c0eaf9dce01883261a5b77410c9408aa447e478efd191b4de6fc1101e796ff5892f8443ef20d9544385819093dbb32d36bd - languageName: node - linkType: hard - -"minipass-pipeline@npm:^1.2.4": - version: 1.2.4 - resolution: "minipass-pipeline@npm:1.2.4" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2 - languageName: node - linkType: hard - -"minipass-sized@npm:^1.0.3": - version: 1.0.3 - resolution: "minipass-sized@npm:1.0.3" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb - languageName: node - linkType: hard - -"minipass@npm:^3.0.0": - version: 3.3.6 - resolution: "minipass@npm:3.3.6" - dependencies: - yallist: "npm:^4.0.0" - checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c - languageName: node - linkType: hard - -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": - version: 7.1.2 - resolution: "minipass@npm:7.1.2" - checksum: 10c0/b0fd20bb9fb56e5fa9a8bfac539e8915ae07430a619e4b86ff71f5fc757ef3924b23b2c4230393af1eda647ed3d75739e4e0acb250a6b1eb277cf7f8fe449557 - languageName: node - linkType: hard - -"minizlib@npm:^3.0.1": - version: 3.0.2 - resolution: "minizlib@npm:3.0.2" - dependencies: - minipass: "npm:^7.1.2" - checksum: 10c0/9f3bd35e41d40d02469cb30470c55ccc21cae0db40e08d1d0b1dff01cc8cc89a6f78e9c5d2b7c844e485ec0a8abc2238111213fdc5b2038e6d1012eacf316f78 - languageName: node - linkType: hard - -"mkdirp@npm:^3.0.1": - version: 3.0.1 - resolution: "mkdirp@npm:3.0.1" - bin: - mkdirp: dist/cjs/src/bin.js - checksum: 10c0/9f2b975e9246351f5e3a40dcfac99fcd0baa31fbfab615fe059fb11e51f10e4803c63de1f384c54d656e4db31d000e4767e9ef076a22e12a641357602e31d57d - languageName: node - linkType: hard - -"module-details-from-path@npm:^1.0.3": - version: 1.0.4 - resolution: "module-details-from-path@npm:1.0.4" - checksum: 10c0/10863413e96dab07dee917eae07afe46f7bf853065cc75a7d2a718adf67574857fb64f8a2c0c9af12ac733a9a8cf652db7ed39b95f7a355d08106cb9cc50c83b - languageName: node - linkType: hard - -"ms@npm:^2.1.3": - version: 2.1.3 - resolution: "ms@npm:2.1.3" - checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 - languageName: node - linkType: hard - -"nanoid@npm:^3.3.8": - version: 3.3.11 - resolution: "nanoid@npm:3.3.11" - bin: - nanoid: bin/nanoid.cjs - checksum: 10c0/40e7f70b3d15f725ca072dfc4f74e81fcf1fbb02e491cf58ac0c79093adc9b0a73b152bcde57df4b79cd097e13023d7504acb38404a4da7bc1cd8e887b82fe0b - languageName: node - linkType: hard - -"negotiator@npm:^1.0.0": - version: 1.0.0 - resolution: "negotiator@npm:1.0.0" - checksum: 10c0/4c559dd52669ea48e1914f9d634227c561221dd54734070791f999c52ed0ff36e437b2e07d5c1f6e32909fc625fe46491c16e4a8f0572567d4dd15c3a4fda04b - languageName: node - linkType: hard - -"node-abi@npm:^3.73.0": - version: 3.75.0 - resolution: "node-abi@npm:3.75.0" - dependencies: - semver: "npm:^7.3.5" - checksum: 10c0/c43a2409407df3737848fd96202b0a49e15039994aecce963969e9ef7342a8fc544aba94e0bfd8155fb9de5f5fe9a4b6ccad8bf509e7c46caf096fc4491d63f2 - languageName: node - linkType: hard - -"node-fetch@npm:^2.6.1": - version: 2.7.0 - resolution: "node-fetch@npm:2.7.0" - dependencies: - whatwg-url: "npm:^5.0.0" - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - checksum: 10c0/b55786b6028208e6fbe594ccccc213cab67a72899c9234eb59dba51062a299ea853210fcf526998eaa2867b0963ad72338824450905679ff0fa304b8c5093ae8 - languageName: node - linkType: hard - -"node-gyp-build-optional-packages@npm:5.1.1": - version: 5.1.1 - resolution: "node-gyp-build-optional-packages@npm:5.1.1" - dependencies: - detect-libc: "npm:^2.0.1" - bin: - node-gyp-build-optional-packages: bin.js - node-gyp-build-optional-packages-optional: optional.js - node-gyp-build-optional-packages-test: build-test.js - checksum: 10c0/f9fad2061c48fb0fc90831cd11d6a7670d731d22a5b00c7d3441b43b4003543299ff64ff2729afe2cefd7d14928e560d469336e5bb00f613932ec2cd56b3665b - languageName: node - linkType: hard - -"node-gyp@npm:latest": - version: 11.2.0 - resolution: "node-gyp@npm:11.2.0" - dependencies: - env-paths: "npm:^2.2.0" - exponential-backoff: "npm:^3.1.1" - graceful-fs: "npm:^4.2.6" - make-fetch-happen: "npm:^14.0.3" - nopt: "npm:^8.0.0" - proc-log: "npm:^5.0.0" - semver: "npm:^7.3.5" - tar: "npm:^7.4.3" - tinyglobby: "npm:^0.2.12" - which: "npm:^5.0.0" - bin: - node-gyp: bin/node-gyp.js - checksum: 10c0/bd8d8c76b06be761239b0c8680f655f6a6e90b48e44d43415b11c16f7e8c15be346fba0cbf71588c7cdfb52c419d928a7d3db353afc1d952d19756237d8f10b9 - languageName: node - linkType: hard - -"nopt@npm:^8.0.0": - version: 8.1.0 - resolution: "nopt@npm:8.1.0" - dependencies: - abbrev: "npm:^3.0.0" - bin: - nopt: bin/nopt.js - checksum: 10c0/62e9ea70c7a3eb91d162d2c706b6606c041e4e7b547cbbb48f8b3695af457dd6479904d7ace600856bf923dd8d1ed0696f06195c8c20f02ac87c1da0e1d315ef - languageName: node - linkType: hard - -"oauth4webapi@npm:^3.5.1": - version: 3.5.1 - resolution: "oauth4webapi@npm:3.5.1" - checksum: 10c0/5d57ba4299d61173b28ff0612fdfcc550b02c2ce4afcd1641103960c02af18268b55a70f26d47bbfc956680967c307546284b4a0b1f13845589e247f798ff395 - languageName: node - linkType: hard - -"obuf@npm:~1.1.2": - version: 1.1.2 - resolution: "obuf@npm:1.1.2" - checksum: 10c0/520aaac7ea701618eacf000fc96ae458e20e13b0569845800fc582f81b386731ab22d55354b4915d58171db00e79cfcd09c1638c02f89577ef092b38c65b7d81 - languageName: node - linkType: hard - -"on-change@npm:^5.0.1": - version: 5.0.1 - resolution: "on-change@npm:5.0.1" - checksum: 10c0/3be9929f45af820288ff3c104290e8bf6346889a51f7b0ccb6eb20802e5b84e34917811a5f267c3fa94729061be99c7aeb99036d1ce6099c673551e8beb04d0a - languageName: node - linkType: hard - -"open@npm:^10.1.0": - version: 10.1.2 - resolution: "open@npm:10.1.2" - dependencies: - default-browser: "npm:^5.2.1" - define-lazy-prop: "npm:^3.0.0" - is-inside-container: "npm:^1.0.0" - is-wsl: "npm:^3.1.0" - checksum: 10c0/1bee796f06e549ce764f693272100323fbc04da8fa3c5b0402d6c2d11b3d76fa0aac0be7535e710015ff035326638e3b9a563f3b0e7ac3266473ed5663caae6d - languageName: node - linkType: hard - -"openapi3-ts@npm:^4.1.2": - version: 4.4.0 - resolution: "openapi3-ts@npm:4.4.0" - dependencies: - yaml: "npm:^2.5.0" - checksum: 10c0/900b834279fc8a43c545728ad75ec7c26934ec5344225b60d1e1c0df44d742d7e7379aea18d9034e03031f079d3308ba5a68600682eece3ed41cdbdd10346a9e - languageName: node - linkType: hard - -"openid-client@npm:^6.5.0": - version: 6.5.0 - resolution: "openid-client@npm:6.5.0" - dependencies: - jose: "npm:^6.0.10" - oauth4webapi: "npm:^3.5.1" - checksum: 10c0/403a1b0d08b5f74d6f715f139ffede1f9a96ca22d59a34c09c8f154159c2e5acf3f396cabc1a7e5fcc93530fc86e6e6d08040df3f42edd3f248ef530445c8651 - languageName: node - linkType: hard - -"p-map@npm:^7.0.2": - version: 7.0.3 - resolution: "p-map@npm:7.0.3" - checksum: 10c0/46091610da2b38ce47bcd1d8b4835a6fa4e832848a6682cf1652bc93915770f4617afc844c10a77d1b3e56d2472bb2d5622353fa3ead01a7f42b04fc8e744a5c - languageName: node - linkType: hard - -"p-retry@npm:^6.2.1": - version: 6.2.1 - resolution: "p-retry@npm:6.2.1" - dependencies: - "@types/retry": "npm:0.12.2" - is-network-error: "npm:^1.0.0" - retry: "npm:^0.13.1" - checksum: 10c0/10d014900107da2c7071ad60fffe4951675f09930b7a91681643ea224ae05649c05001d9e78436d902fe8b116d520dd1f60e72e091de097e2640979d56f3fb60 - languageName: node - linkType: hard - -"package-json-from-dist@npm:^1.0.0": - version: 1.0.1 - resolution: "package-json-from-dist@npm:1.0.1" - checksum: 10c0/62ba2785eb655fec084a257af34dbe24292ab74516d6aecef97ef72d4897310bc6898f6c85b5cd22770eaa1ce60d55a0230e150fb6a966e3ecd6c511e23d164b - languageName: node - linkType: hard - -"path-key@npm:^3.1.0": - version: 3.1.1 - resolution: "path-key@npm:3.1.1" - checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c - languageName: node - linkType: hard - -"path-parse@npm:^1.0.7": - version: 1.0.7 - resolution: "path-parse@npm:1.0.7" - checksum: 10c0/11ce261f9d294cc7a58d6a574b7f1b935842355ec66fba3c3fd79e0f036462eaf07d0aa95bb74ff432f9afef97ce1926c720988c6a7451d8a584930ae7de86e1 - languageName: node - linkType: hard - -"path-scurry@npm:^1.11.1": - version: 1.11.1 - resolution: "path-scurry@npm:1.11.1" - dependencies: - lru-cache: "npm:^10.2.0" - minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - checksum: 10c0/32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d - languageName: node - linkType: hard - -"pathe@npm:^2.0.3": - version: 2.0.3 - resolution: "pathe@npm:2.0.3" - checksum: 10c0/c118dc5a8b5c4166011b2b70608762e260085180bb9e33e80a50dcdb1e78c010b1624f4280c492c92b05fc276715a4c357d1f9edc570f8f1b3d90b6839ebaca1 - languageName: node - linkType: hard - -"pathval@npm:^2.0.0": - version: 2.0.0 - resolution: "pathval@npm:2.0.0" - checksum: 10c0/602e4ee347fba8a599115af2ccd8179836a63c925c23e04bd056d0674a64b39e3a081b643cc7bc0b84390517df2d800a46fcc5598d42c155fe4977095c2f77c5 - languageName: node - linkType: hard - -"pg-int8@npm:1.0.1": - version: 1.0.1 - resolution: "pg-int8@npm:1.0.1" - checksum: 10c0/be6a02d851fc2a4ae3e9de81710d861de3ba35ac927268973eb3cb618873a05b9424656df464dd43bd7dc3fc5295c3f5b3c8349494f87c7af50ec59ef14e0b98 - languageName: node - linkType: hard - -"pg-numeric@npm:1.0.2": - version: 1.0.2 - resolution: "pg-numeric@npm:1.0.2" - checksum: 10c0/43dd9884e7b52c79ddc28d2d282d7475fce8bba13452d33c04ceb2e0a65f561edf6699694e8e1c832ff9093770496363183c950dd29608e1bdd98f344b25bca9 - languageName: node - linkType: hard - -"pg-protocol@npm:*": - version: 1.10.0 - resolution: "pg-protocol@npm:1.10.0" - checksum: 10c0/7d0d64fe9df50262d907fd476454e1e36f41f5f66044c3ba6aa773fb8add1d350a9c162306e5c33e99bdfbdcc1140dd4ca74f66eda41d0aaceb5853244dcdb65 - languageName: node - linkType: hard - -"pg-types@npm:^2.2.0": - version: 2.2.0 - resolution: "pg-types@npm:2.2.0" - dependencies: - pg-int8: "npm:1.0.1" - postgres-array: "npm:~2.0.0" - postgres-bytea: "npm:~1.0.0" - postgres-date: "npm:~1.0.4" - postgres-interval: "npm:^1.1.0" - checksum: 10c0/ab3f8069a323f601cd2d2279ca8c425447dab3f9b61d933b0601d7ffc00d6200df25e26a4290b2b0783b59278198f7dd2ed03e94c4875797919605116a577c65 - languageName: node - linkType: hard - -"pg-types@npm:^4.0.1": - version: 4.0.2 - resolution: "pg-types@npm:4.0.2" - dependencies: - pg-int8: "npm:1.0.1" - pg-numeric: "npm:1.0.2" - postgres-array: "npm:~3.0.1" - postgres-bytea: "npm:~3.0.0" - postgres-date: "npm:~2.1.0" - postgres-interval: "npm:^3.0.0" - postgres-range: "npm:^1.1.1" - checksum: 10c0/780fccda2f3fa2a34e85a72e8e7dadb7d88fbe71ce88f126cb3313f333ad836d02488ec4ff3d94d0c1e5846f735d6e6c6281f8059e6b8919d2180429acaec3e2 - languageName: node - linkType: hard - -"picocolors@npm:^1.1.1": - version: 1.1.1 - resolution: "picocolors@npm:1.1.1" - checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58 - languageName: node - linkType: hard - -"picomatch@npm:^4.0.2": - version: 4.0.2 - resolution: "picomatch@npm:4.0.2" - checksum: 10c0/7c51f3ad2bb42c776f49ebf964c644958158be30d0a510efd5a395e8d49cb5acfed5b82c0c5b365523ce18e6ab85013c9ebe574f60305892ec3fa8eee8304ccc - languageName: node - linkType: hard - -"postcss@npm:^8.5.3": - version: 8.5.3 - resolution: "postcss@npm:8.5.3" - dependencies: - nanoid: "npm:^3.3.8" - picocolors: "npm:^1.1.1" - source-map-js: "npm:^1.2.1" - checksum: 10c0/b75510d7b28c3ab728c8733dd01538314a18c52af426f199a3c9177e63eb08602a3938bfb66b62dc01350b9aed62087eabbf229af97a1659eb8d3513cec823b3 - languageName: node - linkType: hard - -"postgres-array@npm:~2.0.0": - version: 2.0.0 - resolution: "postgres-array@npm:2.0.0" - checksum: 10c0/cbd56207e4141d7fbf08c86f2aebf21fa7064943d3f808ec85f442ff94b48d891e7a144cc02665fb2de5dbcb9b8e3183a2ac749959e794b4a4cfd379d7a21d08 - languageName: node - linkType: hard - -"postgres-array@npm:~3.0.1": - version: 3.0.4 - resolution: "postgres-array@npm:3.0.4" - checksum: 10c0/47f3e648da512bacdd6a5ed55cf770605ec271330789faeece0fd13805a49f376d6e5c9e0e353377be11a9545e727dceaa2473566c505432bf06366ccd04c6b2 - languageName: node - linkType: hard - -"postgres-bytea@npm:~1.0.0": - version: 1.0.0 - resolution: "postgres-bytea@npm:1.0.0" - checksum: 10c0/febf2364b8a8953695cac159eeb94542ead5886792a9627b97e33f6b5bb6e263bc0706ab47ec221516e79fbd6b2452d668841830fb3b49ec6c0fc29be61892ce - languageName: node - linkType: hard - -"postgres-bytea@npm:~3.0.0": - version: 3.0.0 - resolution: "postgres-bytea@npm:3.0.0" - dependencies: - obuf: "npm:~1.1.2" - checksum: 10c0/41c79cc48aa730c5ba3eda6ab989a940034f07a1f57b8f2777dce56f1b8cca16c5870582932b5b10cc605048aef9b6157e06253c871b4717cafc6d00f55376aa - languageName: node - linkType: hard - -"postgres-date@npm:~1.0.4": - version: 1.0.7 - resolution: "postgres-date@npm:1.0.7" - checksum: 10c0/0ff91fccc64003e10b767fcfeefb5eaffbc522c93aa65d5051c49b3c4ce6cb93ab091a7d22877a90ad60b8874202c6f1d0f935f38a7235ed3b258efd54b97ca9 - languageName: node - linkType: hard - -"postgres-date@npm:~2.1.0": - version: 2.1.0 - resolution: "postgres-date@npm:2.1.0" - checksum: 10c0/00a7472c10788f6b0d08d24108bf1eb80858de1bd6317740198a564918ea4a69b80c98148167b92ae688abd606483020d0de0dd3a36f3ea9a3e26bbeef3464f4 - languageName: node - linkType: hard - -"postgres-interval@npm:^1.1.0": - version: 1.2.0 - resolution: "postgres-interval@npm:1.2.0" - dependencies: - xtend: "npm:^4.0.0" - checksum: 10c0/c1734c3cb79e7f22579af0b268a463b1fa1d084e742a02a7a290c4f041e349456f3bee3b4ee0bb3f226828597f7b76deb615c1b857db9a742c45520100456272 - languageName: node - linkType: hard - -"postgres-interval@npm:^3.0.0": - version: 3.0.0 - resolution: "postgres-interval@npm:3.0.0" - checksum: 10c0/8b570b30ea37c685e26d136d34460f246f98935a1533defc4b53bb05ee23ae3dc7475b718ec7ea607a57894d8c6b4f1adf67ca9cc83a75bdacffd427d5c68de8 - languageName: node - linkType: hard - -"postgres-range@npm:^1.1.1": - version: 1.1.4 - resolution: "postgres-range@npm:1.1.4" - checksum: 10c0/254494ef81df208e0adeae6b66ce394aba37914ea14c7ece55a45fb6691b7db04bee74c825380a47c887a9f87158fd3d86f758f9cc60b76d3a38ce5aca7912e8 - languageName: node - linkType: hard - -"proc-log@npm:^5.0.0": - version: 5.0.0 - resolution: "proc-log@npm:5.0.0" - checksum: 10c0/bbe5edb944b0ad63387a1d5b1911ae93e05ce8d0f60de1035b218cdcceedfe39dbd2c697853355b70f1a090f8f58fe90da487c85216bf9671f9499d1a897e9e3 - languageName: node - linkType: hard - -"promise-retry@npm:^2.0.1": - version: 2.0.1 - resolution: "promise-retry@npm:2.0.1" - dependencies: - err-code: "npm:^2.0.2" - retry: "npm:^0.12.0" - checksum: 10c0/9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96 - languageName: node - linkType: hard - -"readdirp@npm:^4.0.1": - version: 4.1.2 - resolution: "readdirp@npm:4.1.2" - checksum: 10c0/60a14f7619dec48c9c850255cd523e2717001b0e179dc7037cfa0895da7b9e9ab07532d324bfb118d73a710887d1e35f79c495fa91582784493e085d18c72c62 - languageName: node - linkType: hard - -"require-in-the-middle@npm:^7.1.1": - version: 7.5.2 - resolution: "require-in-the-middle@npm:7.5.2" - dependencies: - debug: "npm:^4.3.5" - module-details-from-path: "npm:^1.0.3" - resolve: "npm:^1.22.8" - checksum: 10c0/43a2dac5520e39d13c413650895715e102d6802e6cc6ff322017bd948f12a9657fe28435f7cbbcba437b167f02e192ac7af29fa35cabd5d0c375d071c0605e01 - languageName: node - linkType: hard - -"resolve-pkg-maps@npm:^1.0.0": - version: 1.0.0 - resolution: "resolve-pkg-maps@npm:1.0.0" - checksum: 10c0/fb8f7bbe2ca281a73b7ef423a1cbc786fb244bd7a95cbe5c3fba25b27d327150beca8ba02f622baea65919a57e061eb5005204daa5f93ed590d9b77463a567ab - languageName: node - linkType: hard - -"resolve@npm:^1.22.8": - version: 1.22.10 - resolution: "resolve@npm:1.22.10" - dependencies: - is-core-module: "npm:^2.16.0" - path-parse: "npm:^1.0.7" - supports-preserve-symlinks-flag: "npm:^1.0.0" - bin: - resolve: bin/resolve - checksum: 10c0/8967e1f4e2cc40f79b7e080b4582b9a8c5ee36ffb46041dccb20e6461161adf69f843b43067b4a375de926a2cd669157e29a29578191def399dd5ef89a1b5203 - languageName: node - linkType: hard - -"resolve@patch:resolve@npm%3A^1.22.8#optional!builtin": - version: 1.22.10 - resolution: "resolve@patch:resolve@npm%3A1.22.10#optional!builtin::version=1.22.10&hash=c3c19d" - dependencies: - is-core-module: "npm:^2.16.0" - path-parse: "npm:^1.0.7" - supports-preserve-symlinks-flag: "npm:^1.0.0" - bin: - resolve: bin/resolve - checksum: 10c0/52a4e505bbfc7925ac8f4cd91fd8c4e096b6a89728b9f46861d3b405ac9a1ccf4dcbf8befb4e89a2e11370dacd0160918163885cbc669369590f2f31f4c58939 - languageName: node - linkType: hard - -"retry@npm:^0.12.0": - version: 0.12.0 - resolution: "retry@npm:0.12.0" - checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe - languageName: node - linkType: hard - -"retry@npm:^0.13.1": - version: 0.13.1 - resolution: "retry@npm:0.13.1" - checksum: 10c0/9ae822ee19db2163497e074ea919780b1efa00431d197c7afdb950e42bf109196774b92a49fc9821f0b8b328a98eea6017410bfc5e8a0fc19c85c6d11adb3772 - languageName: node - linkType: hard - -"rollup@npm:^4.34.9": - version: 4.41.1 - resolution: "rollup@npm:4.41.1" - dependencies: - "@rollup/rollup-android-arm-eabi": "npm:4.41.1" - "@rollup/rollup-android-arm64": "npm:4.41.1" - "@rollup/rollup-darwin-arm64": "npm:4.41.1" - "@rollup/rollup-darwin-x64": "npm:4.41.1" - "@rollup/rollup-freebsd-arm64": "npm:4.41.1" - "@rollup/rollup-freebsd-x64": "npm:4.41.1" - "@rollup/rollup-linux-arm-gnueabihf": "npm:4.41.1" - "@rollup/rollup-linux-arm-musleabihf": "npm:4.41.1" - "@rollup/rollup-linux-arm64-gnu": "npm:4.41.1" - "@rollup/rollup-linux-arm64-musl": "npm:4.41.1" - "@rollup/rollup-linux-loongarch64-gnu": "npm:4.41.1" - "@rollup/rollup-linux-powerpc64le-gnu": "npm:4.41.1" - "@rollup/rollup-linux-riscv64-gnu": "npm:4.41.1" - "@rollup/rollup-linux-riscv64-musl": "npm:4.41.1" - "@rollup/rollup-linux-s390x-gnu": "npm:4.41.1" - "@rollup/rollup-linux-x64-gnu": "npm:4.41.1" - "@rollup/rollup-linux-x64-musl": "npm:4.41.1" - "@rollup/rollup-win32-arm64-msvc": "npm:4.41.1" - "@rollup/rollup-win32-ia32-msvc": "npm:4.41.1" - "@rollup/rollup-win32-x64-msvc": "npm:4.41.1" - "@types/estree": "npm:1.0.7" - fsevents: "npm:~2.3.2" - dependenciesMeta: - "@rollup/rollup-android-arm-eabi": - optional: true - "@rollup/rollup-android-arm64": - optional: true - "@rollup/rollup-darwin-arm64": - optional: true - "@rollup/rollup-darwin-x64": - optional: true - "@rollup/rollup-freebsd-arm64": - optional: true - "@rollup/rollup-freebsd-x64": - optional: true - "@rollup/rollup-linux-arm-gnueabihf": - optional: true - "@rollup/rollup-linux-arm-musleabihf": - optional: true - "@rollup/rollup-linux-arm64-gnu": - optional: true - "@rollup/rollup-linux-arm64-musl": - optional: true - "@rollup/rollup-linux-loongarch64-gnu": - optional: true - "@rollup/rollup-linux-powerpc64le-gnu": - optional: true - "@rollup/rollup-linux-riscv64-gnu": - optional: true - "@rollup/rollup-linux-riscv64-musl": - optional: true - "@rollup/rollup-linux-s390x-gnu": - optional: true - "@rollup/rollup-linux-x64-gnu": - optional: true - "@rollup/rollup-linux-x64-musl": - optional: true - "@rollup/rollup-win32-arm64-msvc": - optional: true - "@rollup/rollup-win32-ia32-msvc": - optional: true - "@rollup/rollup-win32-x64-msvc": - optional: true - fsevents: - optional: true - bin: - rollup: dist/bin/rollup - checksum: 10c0/c4d5f2257320b50dc0e035e31d8d2f78d36b7015aef2f87cc984c0a1c97ffebf14337dddeb488b4b11ae798fea6486189b77e7cf677617dcf611d97db41ebfda - languageName: node - linkType: hard - -"run-applescript@npm:^7.0.0": - version: 7.0.0 - resolution: "run-applescript@npm:7.0.0" - checksum: 10c0/bd821bbf154b8e6c8ecffeaf0c33cebbb78eb2987476c3f6b420d67ab4c5301faa905dec99ded76ebb3a7042b4e440189ae6d85bbbd3fc6e8d493347ecda8bfe - languageName: node - linkType: hard - -"safer-buffer@npm:>= 2.1.2 < 3.0.0": - version: 2.1.2 - resolution: "safer-buffer@npm:2.1.2" - checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 - languageName: node - linkType: hard - -"secure-json-parse@npm:^2.7.0": - version: 2.7.0 - resolution: "secure-json-parse@npm:2.7.0" - checksum: 10c0/f57eb6a44a38a3eeaf3548228585d769d788f59007454214fab9ed7f01fbf2e0f1929111da6db28cf0bcc1a2e89db5219a59e83eeaec3a54e413a0197ce879e4 - languageName: node - linkType: hard - -"semver@npm:^7.3.5, semver@npm:^7.5.2": - version: 7.7.2 - resolution: "semver@npm:7.7.2" - bin: - semver: bin/semver.js - checksum: 10c0/aca305edfbf2383c22571cb7714f48cadc7ac95371b4b52362fb8eeffdfbc0de0669368b82b2b15978f8848f01d7114da65697e56cd8c37b0dab8c58e543f9ea - languageName: node - linkType: hard - -"shebang-command@npm:^2.0.0": - version: 2.0.0 - resolution: "shebang-command@npm:2.0.0" - dependencies: - shebang-regex: "npm:^3.0.0" - checksum: 10c0/a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e - languageName: node - linkType: hard - -"shebang-regex@npm:^3.0.0": - version: 3.0.0 - resolution: "shebang-regex@npm:3.0.0" - checksum: 10c0/1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 - languageName: node - linkType: hard - -"shimmer@npm:^1.2.1": - version: 1.2.1 - resolution: "shimmer@npm:1.2.1" - checksum: 10c0/ae8b27c389db2a00acfc8da90240f11577685a8f3e40008f826a3bea8b4f3b3ecd305c26be024b4a0fd3b123d132c1569d6e238097960a9a543b6c60760fb46a - languageName: node - linkType: hard - -"siginfo@npm:^2.0.0": - version: 2.0.0 - resolution: "siginfo@npm:2.0.0" - checksum: 10c0/3def8f8e516fbb34cb6ae415b07ccc5d9c018d85b4b8611e3dc6f8be6d1899f693a4382913c9ed51a06babb5201639d76453ab297d1c54a456544acf5c892e34 - languageName: node - linkType: hard - -"signal-exit@npm:^4.0.1": - version: 4.1.0 - resolution: "signal-exit@npm:4.1.0" - checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 - languageName: node - linkType: hard - -"smart-buffer@npm:^4.2.0": - version: 4.2.0 - resolution: "smart-buffer@npm:4.2.0" - checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539 - languageName: node - linkType: hard - -"socks-proxy-agent@npm:^8.0.3": - version: 8.0.5 - resolution: "socks-proxy-agent@npm:8.0.5" - dependencies: - agent-base: "npm:^7.1.2" - debug: "npm:^4.3.4" - socks: "npm:^2.8.3" - checksum: 10c0/5d2c6cecba6821389aabf18728325730504bf9bb1d9e342e7987a5d13badd7a98838cc9a55b8ed3cb866ad37cc23e1086f09c4d72d93105ce9dfe76330e9d2a6 - languageName: node - linkType: hard - -"socks@npm:^2.8.3": - version: 2.8.4 - resolution: "socks@npm:2.8.4" - dependencies: - ip-address: "npm:^9.0.5" - smart-buffer: "npm:^4.2.0" - checksum: 10c0/00c3271e233ccf1fb83a3dd2060b94cc37817e0f797a93c560b9a7a86c4a0ec2961fb31263bdd24a3c28945e24868b5f063cd98744171d9e942c513454b50ae5 - languageName: node - linkType: hard - -"source-map-js@npm:^1.2.1": - version: 1.2.1 - resolution: "source-map-js@npm:1.2.1" - checksum: 10c0/7bda1fc4c197e3c6ff17de1b8b2c20e60af81b63a52cb32ec5a5d67a20a7d42651e2cb34ebe93833c5a2a084377e17455854fee3e21e7925c64a51b6a52b0faf - languageName: node - linkType: hard - -"source-map-support@npm:^0.5.21": - version: 0.5.21 - resolution: "source-map-support@npm:0.5.21" - dependencies: - buffer-from: "npm:^1.0.0" - source-map: "npm:^0.6.0" - checksum: 10c0/9ee09942f415e0f721d6daad3917ec1516af746a8120bba7bb56278707a37f1eb8642bde456e98454b8a885023af81a16e646869975f06afc1a711fb90484e7d - languageName: node - linkType: hard - -"source-map@npm:^0.6.0": - version: 0.6.1 - resolution: "source-map@npm:0.6.1" - checksum: 10c0/ab55398007c5e5532957cb0beee2368529618ac0ab372d789806f5718123cc4367d57de3904b4e6a4170eb5a0b0f41373066d02ca0735a0c4d75c7d328d3e011 - languageName: node - linkType: hard - -"sprintf-js@npm:^1.1.3": - version: 1.1.3 - resolution: "sprintf-js@npm:1.1.3" - checksum: 10c0/09270dc4f30d479e666aee820eacd9e464215cdff53848b443964202bf4051490538e5dd1b42e1a65cf7296916ca17640aebf63dae9812749c7542ee5f288dec - languageName: node - linkType: hard - -"ssri@npm:^12.0.0": - version: 12.0.0 - resolution: "ssri@npm:12.0.0" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/caddd5f544b2006e88fa6b0124d8d7b28208b83c72d7672d5ade44d794525d23b540f3396108c4eb9280dcb7c01f0bef50682f5b4b2c34291f7c5e211fd1417d - languageName: node - linkType: hard - -"stackback@npm:0.0.2": - version: 0.0.2 - resolution: "stackback@npm:0.0.2" - checksum: 10c0/89a1416668f950236dd5ac9f9a6b2588e1b9b62b1b6ad8dff1bfc5d1a15dbf0aafc9b52d2226d00c28dffff212da464eaeebfc6b7578b9d180cef3e3782c5983 - languageName: node - linkType: hard - -"std-env@npm:^3.9.0": - version: 3.9.0 - resolution: "std-env@npm:3.9.0" - checksum: 10c0/4a6f9218aef3f41046c3c7ecf1f98df00b30a07f4f35c6d47b28329bc2531eef820828951c7d7b39a1c5eb19ad8a46e3ddfc7deb28f0a2f3ceebee11bab7ba50 - languageName: node - linkType: hard - -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0": - version: 4.2.3 - resolution: "string-width@npm:4.2.3" - dependencies: - emoji-regex: "npm:^8.0.0" - is-fullwidth-code-point: "npm:^3.0.0" - strip-ansi: "npm:^6.0.1" - checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b - languageName: node - linkType: hard - -"string-width@npm:^5.0.1, string-width@npm:^5.1.2": - version: 5.1.2 - resolution: "string-width@npm:5.1.2" - dependencies: - eastasianwidth: "npm:^0.2.0" - emoji-regex: "npm:^9.2.2" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca - languageName: node - linkType: hard - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": - version: 6.0.1 - resolution: "strip-ansi@npm:6.0.1" - dependencies: - ansi-regex: "npm:^5.0.1" - checksum: 10c0/1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952 - languageName: node - linkType: hard - -"strip-ansi@npm:^7.0.1": - version: 7.1.0 - resolution: "strip-ansi@npm:7.1.0" - dependencies: - ansi-regex: "npm:^6.0.1" - checksum: 10c0/a198c3762e8832505328cbf9e8c8381de14a4fa50a4f9b2160138158ea88c0f5549fb50cb13c651c3088f47e63a108b34622ec18c0499b6c8c3a5ddf6b305ac4 - languageName: node - linkType: hard - -"supports-preserve-symlinks-flag@npm:^1.0.0": - version: 1.0.0 - resolution: "supports-preserve-symlinks-flag@npm:1.0.0" - checksum: 10c0/6c4032340701a9950865f7ae8ef38578d8d7053f5e10518076e6554a9381fa91bd9c6850193695c141f32b21f979c985db07265a758867bac95de05f7d8aeb39 - languageName: node - linkType: hard - -"swr@npm:^2.2.5": - version: 2.3.3 - resolution: "swr@npm:2.3.3" - dependencies: - dequal: "npm:^2.0.3" - use-sync-external-store: "npm:^1.4.0" - peerDependencies: - react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - checksum: 10c0/882fc8291912860e0c50eae3470ebf0cd58b0144cb12adcc4b14c5cef913ea06479043830508d8b0b3d4061d99ad8dd52485c9c879fbd4e9b893484e6d8da9e3 - languageName: node - linkType: hard - -"tar@npm:^7.4.3": - version: 7.4.3 - resolution: "tar@npm:7.4.3" - dependencies: - "@isaacs/fs-minipass": "npm:^4.0.0" - chownr: "npm:^3.0.0" - minipass: "npm:^7.1.2" - minizlib: "npm:^3.0.1" - mkdirp: "npm:^3.0.1" - yallist: "npm:^5.0.0" - checksum: 10c0/d4679609bb2a9b48eeaf84632b6d844128d2412b95b6de07d53d8ee8baf4ca0857c9331dfa510390a0727b550fd543d4d1a10995ad86cdf078423fbb8d99831d - languageName: node - linkType: hard - -"throttleit@npm:2.1.0": - version: 2.1.0 - resolution: "throttleit@npm:2.1.0" - checksum: 10c0/1696ae849522cea6ba4f4f3beac1f6655d335e51b42d99215e196a718adced0069e48deaaf77f7e89f526ab31de5b5c91016027da182438e6f9280be2f3d5265 - languageName: node - linkType: hard - -"tinybench@npm:^2.9.0": - version: 2.9.0 - resolution: "tinybench@npm:2.9.0" - checksum: 10c0/c3500b0f60d2eb8db65250afe750b66d51623057ee88720b7f064894a6cb7eb93360ca824a60a31ab16dab30c7b1f06efe0795b352e37914a9d4bad86386a20c - languageName: node - linkType: hard - -"tinyexec@npm:^0.3.2": - version: 0.3.2 - resolution: "tinyexec@npm:0.3.2" - checksum: 10c0/3efbf791a911be0bf0821eab37a3445c2ba07acc1522b1fa84ae1e55f10425076f1290f680286345ed919549ad67527d07281f1c19d584df3b74326909eb1f90 - languageName: node - linkType: hard - -"tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.13": - version: 0.2.14 - resolution: "tinyglobby@npm:0.2.14" - dependencies: - fdir: "npm:^6.4.4" - picomatch: "npm:^4.0.2" - checksum: 10c0/f789ed6c924287a9b7d3612056ed0cda67306cd2c80c249fd280cf1504742b12583a2089b61f4abbd24605f390809017240e250241f09938054c9b363e51c0a6 - languageName: node - linkType: hard - -"tinypool@npm:^1.0.2": - version: 1.0.2 - resolution: "tinypool@npm:1.0.2" - checksum: 10c0/31ac184c0ff1cf9a074741254fe9ea6de95026749eb2b8ec6fd2b9d8ca94abdccda731f8e102e7f32e72ed3b36d32c6975fd5f5523df3f1b6de6c3d8dfd95e63 - languageName: node - linkType: hard - -"tinyrainbow@npm:^2.0.0": - version: 2.0.0 - resolution: "tinyrainbow@npm:2.0.0" - checksum: 10c0/c83c52bef4e0ae7fb8ec6a722f70b5b6fa8d8be1c85792e829f56c0e1be94ab70b293c032dc5048d4d37cfe678f1f5babb04bdc65fd123098800148ca989184f - languageName: node - linkType: hard - -"tinyspy@npm:^3.0.2": - version: 3.0.2 - resolution: "tinyspy@npm:3.0.2" - checksum: 10c0/55ffad24e346622b59292e097c2ee30a63919d5acb7ceca87fc0d1c223090089890587b426e20054733f97a58f20af2c349fb7cc193697203868ab7ba00bcea0 - languageName: node - linkType: hard - -"tr46@npm:~0.0.3": - version: 0.0.3 - resolution: "tr46@npm:0.0.3" - checksum: 10c0/047cb209a6b60c742f05c9d3ace8fa510bff609995c129a37ace03476a9b12db4dbf975e74600830ef0796e18882b2381fb5fb1f6b4f96b832c374de3ab91a11 - languageName: node - linkType: hard - -"tsx@npm:^3.12.7": - version: 3.14.0 - resolution: "tsx@npm:3.14.0" - dependencies: - esbuild: "npm:~0.18.20" - fsevents: "npm:~2.3.3" - get-tsconfig: "npm:^4.7.2" - source-map-support: "npm:^0.5.21" - dependenciesMeta: - fsevents: - optional: true - bin: - tsx: dist/cli.mjs - checksum: 10c0/b6c938bdae9c656aef2aa0130ee6aa8f3487b5d411d5f7934b705c28ff44ab268db3dde123cf5237b4e5e2ab4441a0bad4b1a39e3ff2170d138538e44082f05d - languageName: node - linkType: hard - -"typescript@npm:^5.7.3": - version: 5.8.3 - resolution: "typescript@npm:5.8.3" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10c0/5f8bb01196e542e64d44db3d16ee0e4063ce4f3e3966df6005f2588e86d91c03e1fb131c2581baf0fb65ee79669eea6e161cd448178986587e9f6844446dbb48 - languageName: node - linkType: hard - -"typescript@patch:typescript@npm%3A^5.7.3#optional!builtin": - version: 5.8.3 - resolution: "typescript@patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10c0/39117e346ff8ebd87ae1510b3a77d5d92dae5a89bde588c747d25da5c146603a99c8ee588c7ef80faaf123d89ed46f6dbd918d534d641083177d5fac38b8a1cb - languageName: node - linkType: hard - -"undici-types@npm:~6.21.0": - version: 6.21.0 - resolution: "undici-types@npm:6.21.0" - checksum: 10c0/c01ed51829b10aa72fc3ce64b747f8e74ae9b60eafa19a7b46ef624403508a54c526ffab06a14a26b3120d055e1104d7abe7c9017e83ced038ea5cf52f8d5e04 - languageName: node - linkType: hard - -"unfetch@npm:^4.2.0": - version: 4.2.0 - resolution: "unfetch@npm:4.2.0" - checksum: 10c0/a5c0a896a6f09f278b868075aea65652ad185db30e827cb7df45826fe5ab850124bf9c44c4dafca4bf0c55a0844b17031e8243467fcc38dd7a7d435007151f1b - languageName: node - linkType: hard - -"unique-filename@npm:^4.0.0": - version: 4.0.0 - resolution: "unique-filename@npm:4.0.0" - dependencies: - unique-slug: "npm:^5.0.0" - checksum: 10c0/38ae681cceb1408ea0587b6b01e29b00eee3c84baee1e41fd5c16b9ed443b80fba90c40e0ba69627e30855570a34ba8b06702d4a35035d4b5e198bf5a64c9ddc - languageName: node - linkType: hard - -"unique-slug@npm:^5.0.0": - version: 5.0.0 - resolution: "unique-slug@npm:5.0.0" - dependencies: - imurmurhash: "npm:^0.1.4" - checksum: 10c0/d324c5a44887bd7e105ce800fcf7533d43f29c48757ac410afd42975de82cc38ea2035c0483f4de82d186691bf3208ef35c644f73aa2b1b20b8e651be5afd293 - languageName: node - linkType: hard - -"use-sync-external-store@npm:^1.4.0": - version: 1.5.0 - resolution: "use-sync-external-store@npm:1.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - checksum: 10c0/1b8663515c0be34fa653feb724fdcce3984037c78dd4a18f68b2c8be55cc1a1084c578d5b75f158d41b5ddffc2bf5600766d1af3c19c8e329bb20af2ec6f52f4 - languageName: node - linkType: hard - -"vite-node@npm:3.1.4": - version: 3.1.4 - resolution: "vite-node@npm:3.1.4" - dependencies: - cac: "npm:^6.7.14" - debug: "npm:^4.4.0" - es-module-lexer: "npm:^1.7.0" - pathe: "npm:^2.0.3" - vite: "npm:^5.0.0 || ^6.0.0" - bin: - vite-node: vite-node.mjs - checksum: 10c0/2fc71ddadd308b19b0d0dc09f5b9a108ea9bb640ec5fbd6179267994da8fd6c9d6a4c92098af7de73a0fa817055b518b28972452a2f19a1be754e79947e289d2 - languageName: node - linkType: hard - -"vite@npm:^5.0.0 || ^6.0.0": - version: 6.3.5 - resolution: "vite@npm:6.3.5" - dependencies: - esbuild: "npm:^0.25.0" - fdir: "npm:^6.4.4" - fsevents: "npm:~2.3.3" - picomatch: "npm:^4.0.2" - postcss: "npm:^8.5.3" - rollup: "npm:^4.34.9" - tinyglobby: "npm:^0.2.13" - peerDependencies: - "@types/node": ^18.0.0 || ^20.0.0 || >=22.0.0 - jiti: ">=1.21.0" - less: "*" - lightningcss: ^1.21.0 - sass: "*" - sass-embedded: "*" - stylus: "*" - sugarss: "*" - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - dependenciesMeta: - fsevents: - optional: true - peerDependenciesMeta: - "@types/node": - optional: true - jiti: - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true - bin: - vite: bin/vite.js - checksum: 10c0/df70201659085133abffc6b88dcdb8a57ef35f742a01311fc56a4cfcda6a404202860729cc65a2c401a724f6e25f9ab40ce4339ed4946f550541531ced6fe41c - languageName: node - linkType: hard - -"vitest@npm:^3.1.1": - version: 3.1.4 - resolution: "vitest@npm:3.1.4" - dependencies: - "@vitest/expect": "npm:3.1.4" - "@vitest/mocker": "npm:3.1.4" - "@vitest/pretty-format": "npm:^3.1.4" - "@vitest/runner": "npm:3.1.4" - "@vitest/snapshot": "npm:3.1.4" - "@vitest/spy": "npm:3.1.4" - "@vitest/utils": "npm:3.1.4" - chai: "npm:^5.2.0" - debug: "npm:^4.4.0" - expect-type: "npm:^1.2.1" - magic-string: "npm:^0.30.17" - pathe: "npm:^2.0.3" - std-env: "npm:^3.9.0" - tinybench: "npm:^2.9.0" - tinyexec: "npm:^0.3.2" - tinyglobby: "npm:^0.2.13" - tinypool: "npm:^1.0.2" - tinyrainbow: "npm:^2.0.0" - vite: "npm:^5.0.0 || ^6.0.0" - vite-node: "npm:3.1.4" - why-is-node-running: "npm:^2.3.0" - peerDependencies: - "@edge-runtime/vm": "*" - "@types/debug": ^4.1.12 - "@types/node": ^18.0.0 || ^20.0.0 || >=22.0.0 - "@vitest/browser": 3.1.4 - "@vitest/ui": 3.1.4 - happy-dom: "*" - jsdom: "*" - peerDependenciesMeta: - "@edge-runtime/vm": - optional: true - "@types/debug": - optional: true - "@types/node": - optional: true - "@vitest/browser": - optional: true - "@vitest/ui": - optional: true - happy-dom: - optional: true - jsdom: - optional: true - bin: - vitest: vitest.mjs - checksum: 10c0/aec575e3cc6cf9b3cee224ae63569479e3a41fa980e495a73d384e31e273f34b18317a0da23bbd577c60fe5e717fa41cdc390de4049ce224ffdaa266ea0cdc67 - languageName: node - linkType: hard - -"webidl-conversions@npm:^3.0.0": - version: 3.0.1 - resolution: "webidl-conversions@npm:3.0.1" - checksum: 10c0/5612d5f3e54760a797052eb4927f0ddc01383550f542ccd33d5238cfd65aeed392a45ad38364970d0a0f4fea32e1f4d231b3d8dac4a3bdd385e5cf802ae097db - languageName: node - linkType: hard - -"whatwg-url@npm:^5.0.0": - version: 5.0.0 - resolution: "whatwg-url@npm:5.0.0" - dependencies: - tr46: "npm:~0.0.3" - webidl-conversions: "npm:^3.0.0" - checksum: 10c0/1588bed84d10b72d5eec1d0faa0722ba1962f1821e7539c535558fb5398d223b0c50d8acab950b8c488b4ba69043fd833cc2697056b167d8ad46fac3995a55d5 - languageName: node - linkType: hard - -"which@npm:^2.0.1": - version: 2.0.2 - resolution: "which@npm:2.0.2" - dependencies: - isexe: "npm:^2.0.0" - bin: - node-which: ./bin/node-which - checksum: 10c0/66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f - languageName: node - linkType: hard - -"which@npm:^5.0.0": - version: 5.0.0 - resolution: "which@npm:5.0.0" - dependencies: - isexe: "npm:^3.1.1" - bin: - node-which: bin/which.js - checksum: 10c0/e556e4cd8b7dbf5df52408c9a9dd5ac6518c8c5267c8953f5b0564073c66ed5bf9503b14d876d0e9c7844d4db9725fb0dcf45d6e911e17e26ab363dc3965ae7b - languageName: node - linkType: hard - -"why-is-node-running@npm:^2.3.0": - version: 2.3.0 - resolution: "why-is-node-running@npm:2.3.0" - dependencies: - siginfo: "npm:^2.0.0" - stackback: "npm:0.0.2" - bin: - why-is-node-running: cli.js - checksum: 10c0/1cde0b01b827d2cf4cb11db962f3958b9175d5d9e7ac7361d1a7b0e2dc6069a263e69118bd974c4f6d0a890ef4eedfe34cf3d5167ec14203dbc9a18620537054 - languageName: node - linkType: hard - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version: 7.0.0 - resolution: "wrap-ansi@npm:7.0.0" - dependencies: - ansi-styles: "npm:^4.0.0" - string-width: "npm:^4.1.0" - strip-ansi: "npm:^6.0.0" - checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da - languageName: node - linkType: hard - -"wrap-ansi@npm:^8.1.0": - version: 8.1.0 - resolution: "wrap-ansi@npm:8.1.0" - dependencies: - ansi-styles: "npm:^6.1.0" - string-width: "npm:^5.0.1" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 - languageName: node - linkType: hard - -"ws@npm:^8.17.0": - version: 8.18.2 - resolution: "ws@npm:8.18.2" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 10c0/4b50f67931b8c6943c893f59c524f0e4905bbd183016cfb0f2b8653aa7f28dad4e456b9d99d285bbb67cca4fedd9ce90dfdfaa82b898a11414ebd66ee99141e4 - languageName: node - linkType: hard - -"xtend@npm:^4.0.0": - version: 4.0.2 - resolution: "xtend@npm:4.0.2" - checksum: 10c0/366ae4783eec6100f8a02dff02ac907bf29f9a00b82ac0264b4d8b832ead18306797e283cf19de776538babfdcb2101375ec5646b59f08c52128ac4ab812ed0e - languageName: node - linkType: hard - -"yallist@npm:^4.0.0": - version: 4.0.0 - resolution: "yallist@npm:4.0.0" - checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a - languageName: node - linkType: hard - -"yallist@npm:^5.0.0": - version: 5.0.0 - resolution: "yallist@npm:5.0.0" - checksum: 10c0/a499c81ce6d4a1d260d4ea0f6d49ab4da09681e32c3f0472dee16667ed69d01dae63a3b81745a24bd78476ec4fcf856114cb4896ace738e01da34b2c42235416 - languageName: node - linkType: hard - -"yaml@npm:^2.5.0": - version: 2.8.0 - resolution: "yaml@npm:2.8.0" - bin: - yaml: bin.mjs - checksum: 10c0/f6f7310cf7264a8107e72c1376f4de37389945d2fb4656f8060eca83f01d2d703f9d1b925dd8f39852a57034fafefde6225409ddd9f22aebfda16c6141b71858 - languageName: node - linkType: hard - -"yoga-wasm-web@npm:0.3.3": - version: 0.3.3 - resolution: "yoga-wasm-web@npm:0.3.3" - checksum: 10c0/d46ae3a436409e89eb0ea3b8c7624dafaf2c846d9038fdf8aa0cc839f73a2577b679bdc22997596177de74c580a6cdc3206c98fd2acd91b66f85462d9d9d260a - languageName: node - linkType: hard - -"zod-to-json-schema@npm:^3.24.1": - version: 3.24.5 - resolution: "zod-to-json-schema@npm:3.24.5" - peerDependencies: - zod: ^3.24.1 - checksum: 10c0/0745b94ba53e652d39f262641cdeb2f75d24339fb6076a38ce55bcf53d82dfaea63adf524ebc5f658681005401687f8e9551c4feca7c4c882e123e66091dfb90 - languageName: node - linkType: hard - -"zod@npm:^3.24.1, zod@npm:^3.24.2": - version: 3.25.32 - resolution: "zod@npm:3.25.32" - checksum: 10c0/de0bc052a7666578b3d5dd42bc522f02f27e1c798236439c0f6b6bc1b311a221706aebdafb1f58399d5f558b1fab7860c6970e096fe8d6947743bc791d567c4b - languageName: node - linkType: hard diff --git a/examples/multitenant-deploys/Dockerfile b/examples/multitenant-deploys/Dockerfile deleted file mode 100644 index 56718aca46..0000000000 --- a/examples/multitenant-deploys/Dockerfile +++ /dev/null @@ -1,27 +0,0 @@ -FROM node:18-alpine - -WORKDIR /app - -# Install rivet CLI -RUN apk add --no-cache curl unzip -RUN curl -fsSL https://releases.rivet.gg/rivet/latest/install.sh | sh - -# Copy package files and install dependencies -COPY package.json yarn.lock ./ -RUN yarn install --frozen-lockfile - -# Copy application code -COPY . . - -# Build the application -RUN yarn build - -# Expose the port the app will run on -EXPOSE 3000 - -# Create a non-root user -RUN addgroup -S appgroup && adduser -S appuser -G appgroup -USER appuser - -# Start the application -CMD ["node", "dist/index.js"] \ No newline at end of file diff --git a/examples/multitenant-deploys/README.md b/examples/multitenant-deploys/README.md deleted file mode 100644 index e98eba2dac..0000000000 --- a/examples/multitenant-deploys/README.md +++ /dev/null @@ -1,122 +0,0 @@ -# Multitenant Deploys for Rivet - -A simple Node.js service for handling multi-tenant deployments with Rivet. - -## Features - -- Accepts source code uploads via a multipart POST request -- Validates the presence of a Dockerfile -- Deploys the code to Rivet using `rivet publish` -- Sets up a custom domain route for the application - -## Getting Started - -### Prerequisites - -- Node.js -- [Rivet CLI](https://rivet.gg/docs/install) -- Rivet cloud token ([instructions on how to generate](https://rivet.gg/docs/tokens#cloud-token)) -- Rivet project ID - - For example if your project is at `https://hub.rivet.gg/projects/foobar`, the ID is `foobar` -- Rivet environment ID - - For example if your environment is at `https://hub.rivet.gg/projects/foobar/environments/prod`, the ID is `prod` - -### Environment Variables - -You'll need to set the following environment variables: - -```bash -RIVET_CLOUD_TOKEN=your_rivet_cloud_token -RIVET_PROJECT=your_project_id -RIVET_ENVIRONMENT=your_environment_name -PORT=3000 # Optional, defaults to 3000 -``` - -You can do this by using [`export`](https://askubuntu.com/a/58828) or [dotenv](https://www.npmjs.com/package/dotenv). - -### Developing - -```bash -yarn install -yarn dev -``` - -You can now use `POST http://locahlost:3000/deploy/my-app-id`. Read more about example usage below. - -### Testing - -```bash -yarn test -``` - -## API Usage - -`POST /deploy/:appId` - -**Request:** -- URL Path Parameter: - - `appId`: Unique identifier for the application (3-30 characters, lowercase alphanumeric with hyphens) -- Multipart form data containing: - - `Dockerfile`: A valid Dockerfile for the application (required) - - Additional files for the application - -**Response:** -```json -{ - "success": true, - "appId": "your-app-id", - "endpoint": "https://your-app-id.example.com", - "buildOutput": "..." // Output logs from build command -} -``` - -## Example Usage - -```javascript -const appId = "my-app-id"; - -// Form data that includes project files -const formData = new FormData(); - -const serverContent = ` -const http = require("http"); -const server = http.createServer((req, res) => { - res.writeHead(200, { "Content-Type": "text/plain" }); - res.end("Hello from " + process.env.MY_ENV_VAR); -}); -server.listen(8080); -`; -const serverBlob = new Blob([serverContent], { - type: "application/octet-stream" -}); -formData.append("server.js", serverBlob, "server.js"); - -const dockerfileContent = ` -FROM node:22-alpine -WORKDIR /app -COPY . . - -# Set env var from build arg -ARG MY_ENV_VAR -ENV MY_ENV_VAR=$MY_ENV_VAR - -# Create a non-root user -RUN addgroup -S rivetgroup && adduser -S rivet -G rivetgroup -USER rivet - -CMD ["node", "server.js"] -`; -const dockerfileBlob = new Blob([dockerfileContent], { - type: "application/octet-stream" -}); -formData.append("Dockerfile", dockerfileBlob, "Dockerfile"); - -// Run the deploy -const response = fetch(`http://localhost:3000/deploy/${appId}`, { - method: "POST", - body: formData -}); -if (response.ok) { - const { endpoint } = await response.json(); -} -``` diff --git a/examples/multitenant-deploys/package.json b/examples/multitenant-deploys/package.json deleted file mode 100644 index 3e3dc7b98d..0000000000 --- a/examples/multitenant-deploys/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "multitenant-deploys", - "packageManager": "yarn@4.6.0", - "scripts": { - "dev": "tsx src/index.ts", - "test": "vitest run", - "build": "tsc" - }, - "dependencies": { - "@hono/node-server": "^1.7.0", - "axios": "^1.6.7", - "hono": "^4.0.5", - "temp": "^0.9.4" - }, - "devDependencies": { - "@types/node": "^20.11.19", - "@types/temp": "^0.9.4", - "tsx": "^4.7.0", - "typescript": "^5.3.3", - "vitest": "^1.2.2" - } -} diff --git a/examples/multitenant-deploys/src/app.ts b/examples/multitenant-deploys/src/app.ts deleted file mode 100644 index dd4de1f642..0000000000 --- a/examples/multitenant-deploys/src/app.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { exec } from "node:child_process"; -import * as fs from "node:fs/promises"; -import * as path from "node:path"; -import { promisify } from "node:util"; -import { Hono } from "hono"; -import temp from "temp"; - -const execAsync = promisify(exec); - -// Auto-track and cleanup temp directories/files -temp.track(); - -// Config -const RIVET_CLOUD_TOKEN = process.env.RIVET_CLOUD_TOKEN; -const RIVET_PROJECT = process.env.RIVET_PROJECT; -const RIVET_ENVIRONMENT = process.env.RIVET_ENVIRONMENT; - -if (!RIVET_CLOUD_TOKEN || !RIVET_PROJECT || !RIVET_ENVIRONMENT) { - throw new Error( - "Missing required environment variables: RIVET_CLOUD_TOKEN, RIVET_PROJECT, RIVET_ENVIRONMENT", - ); -} - -export const app = new Hono(); - -app.onError((err, c) => { - console.error("Error during operation:", err); - return c.json( - { - error: "Operation failed", - message: err instanceof Error ? err.message : String(err), - }, - 500, - ); -}); - -app.get("/", (c) => { - return c.text("Multitenant Deploy Example"); -}); - -app.post("/deploy/:appId", async (c) => { - const appId = c.req.param("appId"); - - // Get the form data - const formData = await c.req.formData(); - - if (!appId || typeof appId !== "string") { - return c.json({ error: "Missing or invalid appId" }, 400); - } - - // Validate app ID (alphanumeric and hyphens only, 3-30 chars) - if (!/^[a-z0-9-]{3,30}$/.test(appId)) { - return c.json( - { - error: "Invalid appId format. Must be 3-30 characters, lowercase alphanumeric with hyphens.", - }, - 400, - ); - } - - // Create a temp directory for the files - const tempDir = await temp.mkdir("rivet-deploy-"); - const tempDirProject = path.join(tempDir, "project"); - - // Process and save each file - let hasDockerfile = false; - for (const [fieldName, value] of formData.entries()) { - // Skip non-file fields - if (!(value instanceof File)) continue; - - const filePath = path.join(tempDirProject, fieldName); - - await fs.mkdir(path.dirname(filePath), { recursive: true }); - - await fs.writeFile(filePath, Buffer.from(await value.arrayBuffer())); - - if (fieldName === "Dockerfile") { - hasDockerfile = true; - } - } - - if (!hasDockerfile) { - return c.json({ error: "Dockerfile is required" }, 400); - } - - // Tags unique to this app's functions - const appTags = { - // Specifies that this app is deployed by a user - type: "user-app", - // Specifies which app this function belongs to - // - // Used for attributing billing & more - app: appId, - }; - - // Write Rivet config - const functionName = `fn-${appId}`; - const rivetConfig = { - functions: { - [functionName]: { - build_path: "./project/", - dockerfile: "./Dockerfile", - unstable: { - build_method: "remote", - }, - build_args: { - // See MY_ENV_VAR build args in Dockerfile - MY_ENV_VAR: "custom env var", - APP_ID: appId, - }, - tags: appTags, - route_subpaths: true, - strip_prefix: true, - resources: { cpu: 125, memory: 128 }, - // If you want to host at a subpath: - // path: "/foobar" - }, - }, - }; - await fs.writeFile( - path.join(tempDir, "rivet.json"), - JSON.stringify(rivetConfig), - ); - - // Run rivet publish command - console.log(`Deploying app ${appId} from ${tempDir}...`); - - // Run the deploy command - const deployResult = await execAsync( - `rivet deploy --environment ${RIVET_ENVIRONMENT} --non-interactive`, - { - cwd: tempDir, - }, - ); - - console.log("Publish output:", deployResult.stdout); - - // Get the function endpoint - const endpointResult = await execAsync( - `rivet function endpoint --environment ${RIVET_ENVIRONMENT} ${functionName}`, - { - cwd: tempDir, - }, - ); - - // Strip any extra text and just get the URL - const endpointUrl = endpointResult.stdout.trim(); - console.log("Function endpoint:", endpointUrl); - - return c.json({ - success: true, - appId, - endpoint: endpointUrl, - buildOutput: deployResult.stdout, - }); -}); diff --git a/examples/multitenant-deploys/src/index.ts b/examples/multitenant-deploys/src/index.ts deleted file mode 100644 index 767135b8bb..0000000000 --- a/examples/multitenant-deploys/src/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { serve } from "@hono/node-server"; -import { app } from "./app"; - -const PORT = process.env.PORT || 3000; -console.log(`Server starting on port ${PORT}...`); -serve({ - fetch: app.fetch, - port: Number(PORT), -}); diff --git a/examples/multitenant-deploys/tests/deploy.test.ts b/examples/multitenant-deploys/tests/deploy.test.ts deleted file mode 100644 index e2d1e1f961..0000000000 --- a/examples/multitenant-deploys/tests/deploy.test.ts +++ /dev/null @@ -1,90 +0,0 @@ -import * as fs from "node:fs/promises"; -import * as os from "node:os"; -import * as path from "node:path"; -import { describe, expect, it } from "vitest"; -import { app } from "../src/app"; - -describe("Deploy Endpoint", () => { - it("should deploy an application and return endpoint", async () => { - // Create a temporary Dockerfile for testing - const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "rivet-test-")); - const dockerfilePath = path.join(tempDir, "Dockerfile"); - - await fs.writeFile( - dockerfilePath, - ` -FROM node:22-alpine -WORKDIR /app -COPY . . - -# Set env var from build arg -ARG MY_ENV_VAR -ENV MY_ENV_VAR=$MY_ENV_VAR -ARG APP_ID -ENV APP_ID=$APP_ID - -# Create a non-root user -RUN addgroup -S rivetgroup && adduser -S rivet -G rivetgroup -USER rivet - -CMD ["node", "server.js"] - `, - ); - - // Create a simple server.js file - const serverPath = path.join(tempDir, "server.js"); - await fs.writeFile( - serverPath, - ` -const http = require("http"); -const server = http.createServer((req, res) => { - res.writeHead(200, { "Content-Type": "text/plain" }); - res.end(\`Hello \${process.env.MY_ENV_VAR} from \${process.env.APP_ID}!\`); -}); -// Port defaults to 8080 -console.log("Server started"); -server.listen(8080); - `, - ); - - // Create a FormData instance - const formData = new FormData(); - - // Generate a unique app ID for testing - const testAppId = `test-${Math.floor(Math.random() * 10_000)}`; - - // Add the Dockerfile to the form data - const dockerfileContent = await fs.readFile(dockerfilePath); - const dockerfileBlob = new Blob([dockerfileContent], { - type: "application/octet-stream", - }); - formData.append("Dockerfile", dockerfileBlob, "Dockerfile"); - - // Add server.js to the form data - const serverContent = await fs.readFile(serverPath); - const serverBlob = new Blob([serverContent], { - type: "application/octet-stream", - }); - formData.append("server.js", serverBlob, "server.js"); - - // Make the request to the deploy endpoint - const res = await app.request( - `/deploy/${encodeURIComponent(testAppId)}`, - { - method: "POST", - body: formData, - }, - ); - - // Verify the response - expect(res.status).toBe(200); - - const responseData = await res.json(); - expect(responseData.success).toBe(true); - expect(responseData.appId).toBe(testAppId); - expect(responseData.endpoint).toBeDefined(); - - // Clean up the temporary directory - await fs.rm(tempDir, { recursive: true, force: true }); - }, 120000); // 2 minute timeout for this test -}); diff --git a/examples/multitenant-deploys/tsconfig.json b/examples/multitenant-deploys/tsconfig.json deleted file mode 100644 index ce03e9da31..0000000000 --- a/examples/multitenant-deploys/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "module": "NodeNext", - "moduleResolution": "NodeNext", - "esModuleInterop": true, - "strict": true, - "outDir": "dist", - "skipLibCheck": true - }, - "include": ["src/**/*"] -} diff --git a/examples/s3-streamer/README.md b/examples/s3-streamer/README.md deleted file mode 100644 index 0f57436f18..0000000000 --- a/examples/s3-streamer/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# S3 Streamer Test - -Actors for simple tests of E2E system functionality. - -## Prerequisites - -- [Rivet CLI](https://rivet.gg/docs/setup) - -## Deploying - -```sh -rivet login -rivet deploy -``` - -## Testing - -```sh -rivet deno --populate-env run -A actor_test.ts -``` - diff --git a/examples/s3-streamer/actor.ts b/examples/s3-streamer/actor.ts deleted file mode 100644 index 2d86cda806..0000000000 --- a/examples/s3-streamer/actor.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { Readable } from "node:stream"; -import { GetObjectCommand, S3Client } from "@aws-sdk/client-s3"; -import type { ActorContext } from "@rivet-gg/actor-core"; -import { Hono } from "hono"; - -let s3Client: S3Client; - -// Setup Hono app -const app = new Hono(); - -app.get("/health", (c) => { - return c.text("ok"); -}); - -app.get("/s3-test/:bucket/:key", async (c) => { - try { - const bucket = c.req.param("bucket"); - const key = c.req.param("key"); - - console.log(`Starting S3 stream for ${bucket}/${key}`); - - // Get object from S3 - const response = await s3Client.send( - new GetObjectCommand({ - Bucket: bucket, - Key: key, - }), - ); - - console.log(`Got S3 response for ${bucket}/${key}`); - - // Get content type from S3 response - const contentType = response.ContentType || "application/octet-stream"; - - // Convert S3 stream to Web stream with progress tracking - const webStream1 = response.Body.transformToWebStream(); - console.log("Body type", webStream1.constructor.name); - const s3Stream = Readable.from(webStream1); - let bytesRead = 0; - - const webStream = new ReadableStream({ - start(controller) { - console.log("Starting"); - s3Stream.on("data", (chunk) => { - bytesRead += chunk.length; - console.log( - `Streaming progress for ${bucket}/${key}: ${bytesRead} bytes`, - ); - controller.enqueue(chunk); - }); - s3Stream.on("end", () => { - console.log( - `Completed streaming ${bucket}/${key}: ${bytesRead} total bytes`, - ); - controller.close(); - }); - s3Stream.on("error", (err) => { - console.error(`Error streaming ${bucket}/${key}:`, err); - controller.error(err); - }); - }, - cancel() { - console.log(`Cancelled streaming ${bucket}/${key}`); - s3Stream.destroy(); - }, - }); - - // Return streaming response with proper content type and headers - return new Response(webStream, { - headers: { - "Content-Type": contentType, - "Transfer-Encoding": "chunked", - }, - }); - } catch (error) { - console.error("S3 streaming error:", error); - return c.text("Error streaming from S3", 500); - } -}); - -// Start server -export default { - async start(ctx: ActorContext) { - // Validate required environment variables - const awsAccessKeyId = Deno.env.get("AWS_ACCESS_KEY_ID"); - const awsSecretAccessKey = Deno.env.get("AWS_SECRET_ACCESS_KEY"); - const awsRegion = Deno.env.get("AWS_REGION") || "us-east-1"; - const awsEndpoint = Deno.env.get("AWS_ENDPOINT"); - const portEnv = Deno.env.get("PORT_HTTP"); - - if (!awsAccessKeyId) { - throw new Error("missing AWS_ACCESS_KEY_ID"); - } - if (!awsSecretAccessKey) { - throw new Error("missing AWS_SECRET_ACCESS_KEY"); - } - if (!portEnv) { - throw new Error("missing PORT_HTTP"); - } - - // Initialize S3 client - const s3Config = { - region: awsRegion, - endpoint: awsEndpoint, - credentials: { - accessKeyId: awsAccessKeyId, - secretAccessKey: awsSecretAccessKey, - }, - }; - - s3Client = new S3Client(s3Config); - - // Automatically exit after 1 minute in order to prevent accidental spam - setTimeout(() => { - console.error( - "Actor should've been destroyed by now. Automatically exiting.", - ); - Deno.exit(1); - }, 60 * 1000); - - const port = Number.parseInt(portEnv); - - // Start server - console.log(`Listening on port ${port}`); - const server = Deno.serve({ port }, app.fetch); - await server.finished; - }, -}; diff --git a/examples/s3-streamer/actor_test.ts b/examples/s3-streamer/actor_test.ts deleted file mode 100644 index e631b4968b..0000000000 --- a/examples/s3-streamer/actor_test.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { RivetClient } from "@rivet-gg/api"; - -// Get bucket and key from command line arguments -const bucket = Deno.args[0]; -const key = Deno.args[1]; - -if (!bucket || !key) { - throw new Error("Usage: actor_test.ts "); -} - -// Validate required environment variables -const RIVET_ENDPOINT = Deno.env.get("RIVET_ENDPOINT"); -const RIVET_SERVICE_TOKEN = Deno.env.get("RIVET_SERVICE_TOKEN"); -const RIVET_PROJECT = Deno.env.get("RIVET_PROJECT"); -const RIVET_ENVIRONMENT = Deno.env.get("RIVET_ENVIRONMENT"); -const AWS_ACCESS_KEY_ID = Deno.env.get("AWS_ACCESS_KEY_ID"); -const AWS_SECRET_ACCESS_KEY = Deno.env.get("AWS_SECRET_ACCESS_KEY"); -const AWS_REGION = Deno.env.get("AWS_REGION") || "us-east-1"; -const AWS_ENDPOINT = Deno.env.get("AWS_ENDPOINT"); - -if (!RIVET_ENDPOINT) throw new Error("missing RIVET_ENDPOINT"); -if (!RIVET_SERVICE_TOKEN) throw new Error("missing RIVET_SERVICE_TOKEN"); -if (!RIVET_PROJECT) throw new Error("missing RIVET_PROJECT"); -if (!RIVET_ENVIRONMENT) throw new Error("missing RIVET_ENVIRONMENT"); -if (!AWS_ACCESS_KEY_ID) throw new Error("missing AWS_ACCESS_KEY_ID"); -if (!AWS_SECRET_ACCESS_KEY) throw new Error("missing AWS_SECRET_ACCESS_KEY"); - -// Optional region override -const region = Deno.env.get("REGION") || undefined; - -const client = new RivetClient({ - environment: RIVET_ENDPOINT, - token: RIVET_SERVICE_TOKEN, -}); - -async function run() { - let actorId: string | undefined; - try { - console.log("Creating actor", { region }); - const { actor } = await client.actor.create({ - project: RIVET_PROJECT, - environment: RIVET_ENVIRONMENT, - body: { - region, - tags: { - name: "s3-streamer", - }, - buildTags: { name: "s3-streamer", current: "true" }, - runtime: { - environment: { - AWS_ACCESS_KEY_ID, - AWS_SECRET_ACCESS_KEY, - AWS_REGION, - AWS_ENDPOINT, - }, - }, - network: { - ports: { - http: { - protocol: "https", - routing: { - guard: {}, - }, - }, - }, - }, - lifecycle: { - durable: false, - }, - }, - }); - actorId = actor.id; - - const port = actor.network.ports.http; - const actorOrigin = `${port.protocol}://${port.hostname}:${port.port}${port.path ?? ""}`; - console.log("Created actor at", actorOrigin); - - // Wait for actor to be ready - console.time(`ready-${actorId}`); - while (true) { - try { - const response = await fetch(`${actorOrigin}/health`); - if (response.ok) { - console.log("Health check passed"); - console.timeEnd(`ready-${actorId}`); - break; - } else { - console.error( - `Health check failed with status: ${response.status}, retrying...`, - ); - } - } catch (error) { - console.error("Health check request error:", error); - } - await new Promise((resolve) => setTimeout(resolve, 100)); - } - - console.log("Testing S3 streaming..."); - console.log(`Streaming from S3: ${bucket}/${key}`); - const response = await fetch(`${actorOrigin}/s3-test/${bucket}/${key}`); - - if (response.ok) { - const text = await response.text(); - console.log("Content length:", text.length); - } else { - console.error("S3 streaming failed:", response.status); - throw new Error(`S3 streaming failed: ${response.status}`); - } - } catch (error) { - console.error("Error:", error); - throw error; - } finally { - if (actorId) { - console.log("Destroying", actorId); - await client.actor.destroy(actorId, { - project: RIVET_PROJECT, - environment: RIVET_ENVIRONMENT, - }); - } - } -} - -// Run single test -await run(); diff --git a/examples/s3-streamer/package.json b/examples/s3-streamer/package.json deleted file mode 100644 index 8096bbf71b..0000000000 --- a/examples/s3-streamer/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "s3-streamer", - "version": "1.0.0", - "private": true, - "dependencies": { - "@aws-sdk/client-s3": "^3.511.0", - "hono": "^4.6.17" - }, - "devDependencies": { - "ts-node": "^10.9.2", - "typescript": "^5.3.3" - } -} diff --git a/examples/s3-streamer/rivet.json b/examples/s3-streamer/rivet.json deleted file mode 100644 index ba6a7525b5..0000000000 --- a/examples/s3-streamer/rivet.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "builds": { - "s3-streamer": { - "script": "actor.ts", - "access": "private", - "unstable": { - "minify": false, - "dump_build": true - } - } - } -} diff --git a/examples/s3-streamer/standalone_test.ts b/examples/s3-streamer/standalone_test.ts deleted file mode 100644 index 2aad11b11c..0000000000 --- a/examples/s3-streamer/standalone_test.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { Readable } from "node:stream"; -import { GetObjectCommand, S3Client } from "@aws-sdk/client-s3"; - -// Helper to convert Node streams to Web streams -function nodeStreamToWebStream(nodeStream: Readable) { - return new ReadableStream({ - start(controller) { - console.log("start"); - nodeStream.on("data", (chunk) => { - console.log("data"); - controller.enqueue(chunk); - }); - nodeStream.on("end", () => { - controller.close(); - }); - nodeStream.on("error", (err) => { - console.log("error", err); - controller.error(err); - }); - }, - cancel() { - nodeStream.destroy(); - }, - }); -} - -async function streamS3File( - s3Client: S3Client, - bucket: string, - key: string, -): Promise { - try { - // Get object from S3 - const response = await s3Client.send( - new GetObjectCommand({ - Bucket: bucket, - Key: key, - }), - ); - - // Convert S3 stream to Web stream - //console.log("Body type", response.Body?.constructor.name); - //const s3Stream = Readable.from(response.Body.transformToWebStream()); - const webStream1 = await response.Body.transformToByteArray(); - console.log("Body type", webStream1.constructor.name); - const s3Stream = Readable.from(webStream1); - const webStream = nodeStreamToWebStream(s3Stream); - - // Read the stream into a string - const reader = webStream.getReader(); - const chunks: Uint8Array[] = []; - - while (true) { - const { done, value } = await reader.read(); - if (done) break; - chunks.push(value); - } - - // Combine chunks and convert to string - const allChunks = new Uint8Array( - chunks.reduce((acc, chunk) => acc + chunk.length, 0), - ); - let position = 0; - for (const chunk of chunks) { - allChunks.set(chunk, position); - position += chunk.length; - } - - return new TextDecoder().decode(allChunks); - } catch (error) { - console.error("S3 streaming error:", error); - throw error; - } -} - -async function main() { - const awsAccessKeyId = process.env.AWS_ACCESS_KEY_ID; - const awsSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; - const awsRegion = process.env.AWS_REGION || "us-east-1"; - const awsEndpoint = process.env.AWS_ENDPOINT; - - if (!awsAccessKeyId) { - throw new Error("missing AWS_ACCESS_KEY_ID"); - } - if (!awsSecretAccessKey) { - throw new Error("missing AWS_SECRET_ACCESS_KEY"); - } - - // Initialize S3 client - const s3Config = { - region: awsRegion, - endpoint: awsEndpoint, - credentials: { - accessKeyId: awsAccessKeyId, - secretAccessKey: awsSecretAccessKey, - }, - }; - - const s3Client = new S3Client(s3Config); - - const bucket = process.argv[2]; - const key = process.argv[3]; - - if (!bucket || !key) { - throw new Error("Usage: standalone_test.ts "); - } - - console.log(`Streaming from S3: ${bucket}/${key}`); - - try { - const content = await streamS3File(s3Client, bucket, key); - console.log("Content length:", content.length); - } catch (error) { - console.error("Error:", error); - process.exit(1); - } -} - -main(); - -setInterval(() => {}, 1000); diff --git a/examples/s3-streamer/tsconfig.json b/examples/s3-streamer/tsconfig.json deleted file mode 100644 index afacad332e..0000000000 --- a/examples/s3-streamer/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "compilerOptions": { - "target": "ESNext", - "module": "ESNext", - "moduleResolution": "bundler", - "types": ["node", "deno"], - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - "noEmit": true, - "isolatedModules": true - }, - "include": ["**/*.ts"] -} diff --git a/examples/sandboxed-code-execution-eval/Dockerfile b/examples/sandboxed-code-execution-eval/Dockerfile deleted file mode 100644 index 10a8101893..0000000000 --- a/examples/sandboxed-code-execution-eval/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM denoland/deno:2.2.2 as builder -WORKDIR /app -COPY . . - -# Create non-root user -RUN adduser --disabled-password --gecos "" rivet -USER rivet - -RUN deno cache src/main.ts - -CMD ["deno", "run", "-A", "src/main.ts"] - diff --git a/examples/sandboxed-code-execution-eval/README.md b/examples/sandboxed-code-execution-eval/README.md deleted file mode 100644 index 7b88963fb9..0000000000 --- a/examples/sandboxed-code-execution-eval/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# Sandboxed Code Execution Eval - -This demo runs a Docker container that runs an arbitrary user script. Your application must figure out where to host & download the script. - -## Overview - -- `rivet.json` Config for what to deploy -- `Dockerfile` -- `src/mian.ts` Example server that will spawn a user script -- `fixtures/*.ts` Example user-provided scripts (your service will download these over HTTP) -- `tests/client.ts` Example script that will create & destroy actors - -## Testing - -``` -docker build -t demo . -docker run -p 8080:8080 -e PORT_HTTP=8080 -e USER_CODE_FILE_NAME=date.ts demo -curl localhost:8080 -``` - -## Deploying - -Deploy with: - -``` -rivet deploy -``` - -Test with: - -``` -# `rivet shell` provides credentials to the create_actor.ts script -rivet shell -e "deno run -A scripts/create_actor.ts" -``` - -To integrate the API on your own server: - -```typescript -const { actor } = await client.actor.create({ - project, - environment, - body: { - // This may be whatever you like - tags: { name: "app", foo: "bar" }, - // Must match the name in rivet.json - buildTags: { name: "app" }, - region: region.id, - runtime: { - environment: { - // Configure your container like this - USER_CODE_FILE_NAME: "date.ts", - }, - }, - network: { - ports: { - http: { protocol: "https" } - } - }, - // IMPORTANT: Current hardware only provides 1 CPU : 2 GB of RAM ratios. e.g. 0.5 CPU = 1 GB RAM, 2 CPU = 4 GB RAM, etc - resources: { - cpu: 1000, - memory: 2048, - } - } -}); -``` - diff --git a/examples/sandboxed-code-execution-eval/fixtures/date.ts b/examples/sandboxed-code-execution-eval/fixtures/date.ts deleted file mode 100644 index 16237738b7..0000000000 --- a/examples/sandboxed-code-execution-eval/fixtures/date.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * User Code Example - Date Script - * - * This script logs the current date in ISO format. - * It is executed by the server when an HTTP request is received. - */ - -console.log(`Current date: ${new Date().toISOString()}`); diff --git a/examples/sandboxed-code-execution-eval/fixtures/hello.ts b/examples/sandboxed-code-execution-eval/fixtures/hello.ts deleted file mode 100644 index 2fdb9e2e98..0000000000 --- a/examples/sandboxed-code-execution-eval/fixtures/hello.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * User Code Example - Hello Script - * - * This script logs a hello message. - * It is executed by the server when an HTTP request is received. - */ - -console.log("Hello from user code!"); diff --git a/examples/sandboxed-code-execution-eval/rivet.json b/examples/sandboxed-code-execution-eval/rivet.json deleted file mode 100644 index 6d16021752..0000000000 --- a/examples/sandboxed-code-execution-eval/rivet.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "builds": { - "app": { - "dockerfile": "Dockerfile", - "access": "private" - } - } -} diff --git a/examples/sandboxed-code-execution-eval/scripts/create_actor.ts b/examples/sandboxed-code-execution-eval/scripts/create_actor.ts deleted file mode 100644 index d1a5f31e74..0000000000 --- a/examples/sandboxed-code-execution-eval/scripts/create_actor.ts +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env -S deno run --allow-net --allow-env --allow-read --allow-run - -// Import necessary modules -import { RivetClient } from "npm:@rivet-gg/api@24.6.2" - -async function main() { - const endpoint = Deno.env.get("RIVET_ENDPOINT"); - const token = Deno.env.get("RIVET_SERVICE_TOKEN"); - const project = Deno.env.get("RIVET_PROJECT"); - const environment = Deno.env.get("RIVET_ENVIRONMENT"); - - if (!endpoint || !token || !project || !environment) throw new Error("Missing required env var"); - - const client = new RivetClient({ - environment: endpoint, - token, - }); - - // Find the nearest region (sorted by best to worst) - console.log("Resolving region"); - const { regions: [region] } = await client.actor.regions.list({ project, environment }); - - // Create actor - console.log("Creating"); - const { actor } = await client.actor.create({ - project, - environment, - body: { - // This may be whatever you like - tags: { name: "app", foo: "bar" }, - // Must match the name in rivet.json - buildTags: { name: "app" }, - region: region.id, - runtime: { - environment: { - USER_CODE_FILE_NAME: "date.ts", - }, - }, - network: { - ports: { - http: { protocol: "https" } - } - }, - resources: { - cpu: 1000, - memory: 2048, - } - } - }); - - // Ping actor - console.log("Pinging"); - const response = await fetch( - actor.network.ports.http.url!, - { - method: "POST", - body: "foo", - }, - ); - const responseBody = await response.text(); - console.log("Response", responseBody); - - // Wait - console.log("Sleeping for 5 seconds before destroying."); - await new Promise((resolve) => setTimeout(resolve, 5000)); - - // Destroy actor - console.log("Destroying"); - await client.actor.destroy(actor.id, { project, environment }) -} - -await main(); diff --git a/examples/sandboxed-code-execution-eval/src/main.ts b/examples/sandboxed-code-execution-eval/src/main.ts deleted file mode 100644 index 02261960d1..0000000000 --- a/examples/sandboxed-code-execution-eval/src/main.ts +++ /dev/null @@ -1,99 +0,0 @@ -/** - * Echo HTTP Server with Deno - * - * This server executes user-provided code in a subprocess and returns the output - * as a response to HTTP requests. - */ - -console.log(Deno.env.toObject()); - -// Check for required USER_CODE_FILE_NAME environment variable -const userCodeFileName = Deno.env.get("USER_CODE_FILE_NAME"); -if (!userCodeFileName) { - console.error( - "ERROR: USER_CODE_FILE_NAME environment variable is required", - ); - Deno.exit(1); -} - -console.log(`User code file set to: fixtures/${userCodeFileName}`); - -/** - * Load and run the user code from the specified file path - * - * @returns Object containing success status and output text - */ -async function loadAndRunUserCode(): Promise<{ - success: boolean; - output: string; -}> { - try { - // Construct the path to the user code file - const filePath = `fixtures/${userCodeFileName}`; - - // Run user code as a subprocess with a clean environment - const command = new Deno.Command(Deno.execPath(), { - args: ["run", filePath], - stdout: "piped", - stderr: "piped", - clearEnv: true, // Run with a clean environment (no parent env vars) - }); - - const { code, stdout, stderr } = await command.output(); - - if (code !== 0) { - const errorMessage = new TextDecoder().decode(stderr); - console.error(`Error executing user code: ${errorMessage}`); - return { - success: false, - output: `Error executing user code: ${errorMessage}`, - }; - } - - const output = new TextDecoder().decode(stdout); - console.log(`User code output: ${output}`); - return { - success: true, - output, - }; - } catch (error) { - console.error(`Exception: ${error.message}`); - return { - success: false, - output: `Server error: ${error.message}`, - }; - } -} - -/** - * HTTP request handler - * - * @param req - The incoming HTTP request - * @returns HTTP response with the output from user code execution - */ -async function handler(req: Request): Promise { - console.log("req"); - - const result = await loadAndRunUserCode(); - - if (!result.success) { - return new Response(result.output, { - status: 500, - headers: { "Content-Type": "text/plain" }, - }); - } - - return new Response(result.output, { - status: 200, - headers: { "Content-Type": "text/plain" }, - }); -} - -const port = Number.parseInt(Deno.env.get("PORT_HTTP") || "8000"); -console.log(`Server starting on port ${port}`); - -Deno.serve({ - handler, - port, - hostname: "0.0.0.0", -}); diff --git a/examples/sandboxed-code-execution-standalone/README.md b/examples/sandboxed-code-execution-standalone/README.md deleted file mode 100644 index 4998e1dfbb..0000000000 --- a/examples/sandboxed-code-execution-standalone/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Sandboxed Code Execution Standalone - -This demo uploads a script to Rivet and runs an actor from it. - -## Testing - -Run: - -``` -tsx scripts/upload_js.ts -``` diff --git a/examples/sandboxed-code-execution-standalone/fixtures/echo_http.js b/examples/sandboxed-code-execution-standalone/fixtures/echo_http.js deleted file mode 100644 index 2d5187011a..0000000000 --- a/examples/sandboxed-code-execution-standalone/fixtures/echo_http.js +++ /dev/null @@ -1,22 +0,0 @@ -console.log(Deno.env.toObject()); - -export default { - async start() { - const server = Deno.serve({ - handler, - port: Number.parseInt(Deno.env.get("PORT_HTTP")), - hostname: "0.0.0.0", - }); - - await server.finished; - }, -}; - -function handler(req) { - console.log("req"); - - return new Response(req.body, { - status: 200, - headers: { "Content-Type": "application/json" }, - }); -} diff --git a/examples/sandboxed-code-execution-standalone/scripts/upload_js.ts b/examples/sandboxed-code-execution-standalone/scripts/upload_js.ts deleted file mode 100644 index 5e8fd1ff2b..0000000000 --- a/examples/sandboxed-code-execution-standalone/scripts/upload_js.ts +++ /dev/null @@ -1,169 +0,0 @@ -#!/usr/bin/env -S deno run --allow-net --allow-env --allow-read --allow-run - -// Import necessary modules -import { resolve } from "https://deno.land/std@0.114.0/path/mod.ts"; -import { v4 as uuidv4 } from "https://deno.land/std@0.114.0/uuid/mod.ts"; - -// Constants -const ENDPOINT = Deno.env.get("RIVET_ENDPOINT") ?? "https://api.rivet.gg"; -const BUILD = - Deno.env.get("RIVET_BUILD") ?? - resolve(import.meta.dirname, "./fixtures/echo_http.js"); - -//const PROJECT = "dreamlab-dem-qmv"; -const PROJECT = "dreamlab-dem-qmv"; -const ENV = "prod"; -const TOKEN = process.env.RIVET_SERVICE_TOKEN; - -// Helper function to make HTTP requests -async function httpRequest(method: string, url: string, body?: any) { - const fullUrl = new URL(url); - fullUrl.searchParams.set("project", PROJECT); - fullUrl.searchParams.set("environment", ENV); - - console.log( - `Request: ${method} ${fullUrl.toString()}\n${JSON.stringify(body)}`, - ); - - const response = await fetch(fullUrl.toString(), { - method, - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${TOKEN}`, - }, - body: body ? JSON.stringify(body) : undefined, - }); - const responseText = await response.text(); - - console.log(`Response: ${response.status}\n${responseText}`); - - if (!response.ok) { - throw new Error(`HTTP status: ${response.status}\n\nBody: ${responseText}`); - } - - console.log(); - - return JSON.parse(responseText); -} - -async function listRegions() { - const response = await httpRequest("GET", `${ENDPOINT}/regions`); - return response.regions; -} - -async function uploadBuild() { - // Copy file to tmp directory and rename to index.js - const tmpDir = await Deno.makeTempDir(); - const tmpFilePath = resolve(tmpDir, "index.js"); - await Deno.copyFile(BUILD, tmpFilePath); - - // Archive code - const bundleLocation = resolve(tmpDir, "bundle.tar"); - const tarCommand = new Deno.Command("tar", { - args: ["cf", bundleLocation, "-C", tmpDir, "index.js"], - }); - const { code } = await tarCommand.output(); - console.assert(code === 0); - - const buildContent = await Deno.readFile(bundleLocation); - const contentLength = buildContent.length; - - const randomString = crypto.randomUUID().replace(/-/g, "").slice(0, 8); - const { build, presigned_requests } = await httpRequest( - "POST", - `${ENDPOINT}/builds/prepare`, - { - image_file: { - content_length: contentLength, - path: "bundle.tar", - }, - kind: "javascript", - name: `build-${randomString}`, - }, - ); - - await fetch(presigned_requests[0].url, { - method: "PUT", - body: buildContent, - }); - - await httpRequest("POST", `${ENDPOINT}/builds/${build}/complete`, {}); - - return { buildId: build }; -} - -async function createActor(region: string, buildId: string) { - const createResponse = await httpRequest("POST", `${ENDPOINT}/actors`, { - tags: {}, - region, - network: { - mode: "bridge", - ports: { - http: { protocol: "https" }, - }, - }, - build: buildId, - }); - - while (true) { - const { actor } = await httpRequest( - "GET", - `${ENDPOINT}/actors/${createResponse.actor.id}`, - ); - if (actor.network.ports.http.hostname != null) { - return actor; - } else { - await new Promise((resolve) => setTimeout(resolve, 1000)); - } - } -} - -async function pingActor(actor) { - while (true) { - try { - console.log("Pinging actor"); - - const response = await fetch( - actor.network.ports.http.url, - { - method: "POST", - body: "foo", - }, - ); - const responseBody = await response.text(); - // Validate the response - if (responseBody === "foo") { - console.log("Response validated successfully."); - } else { - console.error("Response validation failed."); - } - - console.log(); - - break; - } catch (err) { - console.log("Failed to ping actor:", err); - await new Promise((resolve) => setTimeout(resolve, 1000)); - } - } -} - -async function destroyActor(actor) { - await httpRequest("DELETE", `${ENDPOINT}/actors/${actor.id}`); -} - -async function main() { - const { buildId } = await uploadBuild(); - - const regions = await listRegions(); - const actor = await createActor(regions[0].id, buildId); - - await pingActor(actor); - - console.log("Sleeping for 5 seconds before destroying."); - await new Promise((resolve) => setTimeout(resolve, 5000)); - - await destroyActor(actor); -} - -await main(); diff --git a/examples/system-test-actor/.dockerignore b/examples/system-test-actor/.dockerignore deleted file mode 100644 index 9ef1530b42..0000000000 --- a/examples/system-test-actor/.dockerignore +++ /dev/null @@ -1,13 +0,0 @@ -.git -.vscode -.idea -node_modules -.env -npm-debug.log -dist -Dockerfile -.dockerignore -.DS_Store -.env.* -*.md -!README.md \ No newline at end of file diff --git a/examples/system-test-actor/Dockerfile b/examples/system-test-actor/Dockerfile deleted file mode 100644 index affb28ca4f..0000000000 --- a/examples/system-test-actor/Dockerfile +++ /dev/null @@ -1,26 +0,0 @@ -# Build stage -FROM node:22 as builder -WORKDIR /app -COPY package.json yarn.lock ./ -RUN yarn install -COPY . . -RUN yarn build - -# Production stage -FROM node:22-slim -WORKDIR /app - -# Create rivet user and set proper permissions -RUN groupadd -r rivet && useradd -r -g rivet rivet -COPY package.json yarn.lock ./ -RUN yarn install --production && \ - chown -R rivet:rivet /app - -COPY --from=builder /app/dist ./dist -RUN chown -R rivet:rivet /app/dist - -# Switch to non-root user -USER rivet - -# Start the server -CMD ["node", "dist/src/container/main.js"] diff --git a/examples/system-test-actor/README.md b/examples/system-test-actor/README.md deleted file mode 100644 index 90f1dc770d..0000000000 --- a/examples/system-test-actor/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# System Test - -Actors for simple tests of E2E system functionality. - -## Prerequisites - -- [Rivet CLI](https://rivet.gg/docs/setup) - -## Deploying - -```sh -rivet deploy -``` - -## Testing - -```sh -BUILD=ws-isolate rivet shell -e "yarn test" -# or -BUILD=ws-container rivet shell -e "yarn test" -``` - diff --git a/examples/system-test-actor/package.json b/examples/system-test-actor/package.json deleted file mode 100644 index 0bf33ca551..0000000000 --- a/examples/system-test-actor/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "system-test-container", - "version": "1.0.0", - "private": true, - "type": "module", - "dependencies": { - "@hono/node-server": "^1.13.8", - "@hono/node-ws": "^1.1.0", - "hono": "^4.6.17" - }, - "devDependencies": { - "@rivet-gg/actor-core": "^5.1.2", - "@rivet-gg/api": "^24.6.2", - "@types/deno": "^2.2.0", - "@types/node": "^22.13.9", - "@types/ws": "^8.18.0", - "dgram": "^1.0.1", - "node-fetch": "^3.3.2", - "tsx": "^4.7.0", - "typescript": "^5.3.3", - "ws": "^8.18.1" - }, - "scripts": { - "start": "tsx ws.ts", - "test": "tsx tests/client.ts", - "build": "tsc --outDir dist" - } -} diff --git a/examples/system-test-actor/rivet.jsonc b/examples/system-test-actor/rivet.jsonc deleted file mode 100644 index d36dd27efc..0000000000 --- a/examples/system-test-actor/rivet.jsonc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "actors": { - "ws-isolate": { - "script": "src/isolate/main.ts" - } - }, - "containers": { - "ws-container": { - "dockerfile": "Dockerfile" - } - } -} diff --git a/examples/system-test-actor/src/container/main.ts b/examples/system-test-actor/src/container/main.ts deleted file mode 100644 index e1157a830a..0000000000 --- a/examples/system-test-actor/src/container/main.ts +++ /dev/null @@ -1,71 +0,0 @@ -import dgram from "dgram"; -import fs from "fs"; -import { serve } from "@hono/node-server"; -import { createNodeWebSocket } from "@hono/node-ws"; -import { createAndStartServer } from "../shared/server.js"; - -// Print hosts file contents before starting -try { - const hostsContent = fs.readFileSync("/etc/hosts", "utf8"); - console.log("=== /etc/hosts contents ==="); - console.log(hostsContent); - console.log("=== End of /etc/hosts ==="); -} catch (err) { - console.error("Failed to read /etc/hosts:", err); -} - -let injectWebSocket: any; -const { app, port } = createAndStartServer((app) => { - // Get Node.js WebSocket handler - const result = createNodeWebSocket({ app }); - injectWebSocket = result.injectWebSocket; - return result.upgradeWebSocket; -}); - -const server = serve({ fetch: app.fetch, port }); -injectWebSocket(server); - -// async function contactApi() { -// console.log('Contacting', process.env.RIVET_API_ENDPOINT); -// const res = await fetch(process.env.RIVET_API_ENDPOINT!); -// console.log('API response', res.ok, res.status); -// } -// -// contactApi(); - -// Get port from environment -const portEnv = - typeof Deno !== "undefined" - ? Deno.env.get("PORT_UDP") - : process.env.PORT_UDP; - -if (portEnv) { - // Create a UDP socket - const udpServer = dgram.createSocket("udp4"); - - // Listen for incoming messages - udpServer.on("message", (msg, rinfo) => { - console.log( - `UDP server received: ${msg} from ${rinfo.address}:${rinfo.port}`, - ); - - // Echo the message back to the sender - udpServer.send(msg, rinfo.port, rinfo.address, (err) => { - if (err) console.error("Failed to send UDP response:", err); - }); - }); - - // Handle errors - udpServer.on("error", (err) => { - console.error("UDP server error:", err); - udpServer.close(); - }); - - const port2 = Number.parseInt(portEnv); - - udpServer.bind(port2, () => { - console.log(`UDP echo server running on port ${port2}`); - }); -} else { - console.warn("missing PORT_UDP"); -} diff --git a/examples/system-test-actor/src/isolate/main.ts b/examples/system-test-actor/src/isolate/main.ts deleted file mode 100644 index ef73cef4d7..0000000000 --- a/examples/system-test-actor/src/isolate/main.ts +++ /dev/null @@ -1,83 +0,0 @@ -import type { ActorContext } from "@rivet-gg/actor-core"; -import { upgradeWebSocket } from "hono/deno"; -import { createAndStartServer } from "../shared/server.js"; - -// Start server -export default { - async start(ctx: ActorContext) { - console.log("Isolate starting"); - - console.log("Metadata:", ctx.metadata); - - // Test KV functionality - console.log("Starting KV API validation"); - console.time("kv-test"); - - console.log("Testing simple put/get/delete operations"); - await ctx.kv.put(["foo", "bar"], 1); - if ((await ctx.kv.get(["foo", "bar"])) !== 1) { - throw new Error("kv get failed - value mismatch"); - } - await ctx.kv.delete(["foo", "bar"]); - - console.log("Testing batch operations"); - await ctx.kv.putBatch( - new Map([ - [["batch", "a"], 2], - [["batch", "b"], 3], - ]), - ); - - console.log("Testing getBatch operations"); - const getBatch = await ctx.kv.getBatch([ - ["batch", "a"], - ["batch", "b"], - ]); - if (getBatch.get(["batch", "a"]) !== 2) { - throw new Error("kv getBatch failed - value mismatch for key a"); - } - if (getBatch.get(["batch", "b"]) !== 3) { - throw new Error("kv getBatch failed - value mismatch for key b"); - } - - console.log("Testing list operations"); - const list = await ctx.kv.list({ - prefix: ["batch"], - }); - if ( - JSON.stringify(list.array()) !== - JSON.stringify([ - [["batch", "a"], 2], - [["batch", "b"], 3], - ]) - ) { - throw new Error( - "kv list failed - results don't match expected values", - ); - } - - console.log("Testing deleteBatch operations"); - await ctx.kv.deleteBatch([ - ["batch", "a"], - ["batch", "b"], - ]); - if ((await ctx.kv.get(["batch", "a"])) !== null) { - throw new Error("kv deleteBatch failed - key still exists"); - } - - console.timeEnd("kv-test"); - console.log("KV API validation complete"); - - // Create and start server with Deno WebSocket upgrader - console.log("Starting HTTP/WebSocket server"); - const { app, port } = createAndStartServer(() => upgradeWebSocket); - - const server = Deno.serve( - { - port, - }, - app.fetch, - ); - await server.finished; - }, -}; diff --git a/examples/system-test-actor/src/shared/server.ts b/examples/system-test-actor/src/shared/server.ts deleted file mode 100644 index f1ee387c20..0000000000 --- a/examples/system-test-actor/src/shared/server.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { type Context, Hono } from "hono"; -import type { UpgradeWebSocket } from "hono/ws"; - -type GetUpgradeWebSocketFn = (app: Hono) => UpgradeWebSocket; - -export function createAndStartServer( - getUpgradeWebSocket: GetUpgradeWebSocketFn, -): { app: Hono; port: number } { - // Setup auto-exit timer - // setTimeout(() => { - // console.error( - // "Actor should've been destroyed by now. Automatically exiting.", - // ); - // - // if (typeof Deno !== "undefined") Deno.exit(1); - // else process.exit(1); - // }, 60 * 1000); - - let tickIndex = 0; - setInterval(() => { - tickIndex++; - console.log("Tick", tickIndex); - }, 1000); - - // Get port from environment - const portEnv = - typeof Deno !== "undefined" - ? Deno.env.get("PORT_HTTP") - : process.env.PORT_HTTP; - if (!portEnv) { - throw new Error("missing PORT_HTTP"); - } - const port = Number.parseInt(portEnv); - - // Create app with health endpoint - const app = new Hono(); - - app.get("/health", (c) => c.text("ok")); - - app.get("/exit", (c) => { - const query = c.req.query("code"); - const exitCode = query ? Number(query) : 0; - - if (typeof Deno != "undefined") Deno.exit(exitCode); - else process.exit(exitCode); - - return c.text("unreachable"); - }); - - // Add WebSocket endpoint with handler - const upgradeWebSocket = getUpgradeWebSocket(app); - app.get( - "/ws", - upgradeWebSocket((c: Context) => { - return { - onOpen(_, ws) { - ws.send( - JSON.stringify([ - "init", - { - forwardedFor: c.req?.header("x-forwarded-for"), - }, - ]), - ); - }, - onMessage(message, ws) { - const data = - typeof message.data === "string" - ? message.data - : (message as unknown as string); - - if (typeof data === "string") { - const [eventType, eventData] = JSON.parse( - data.slice(0, 2 ** 13), - ); - switch (eventType) { - case "ping": - ws.send(JSON.stringify(["pong", eventData])); - break; - default: - console.warn("unknown event", eventType); - break; - } - } - }, - onClose(event) { - console.log( - `WebSocket closed: ${event.code} ${event.reason}`, - ); - }, - onError(event) { - console.error("WebSocket error:", event); - }, - }; - }), - ); - - console.log(`Listening on port ${port}`); - - return { app, port }; -} diff --git a/examples/system-test-actor/tests/client.ts b/examples/system-test-actor/tests/client.ts deleted file mode 100644 index 7521330a31..0000000000 --- a/examples/system-test-actor/tests/client.ts +++ /dev/null @@ -1,235 +0,0 @@ -import dgram from "dgram"; -import { RivetClient } from "@rivet-gg/api"; -import WebSocket from "ws"; - -// Can be opt since they're not required for dev -const RIVET_ENDPOINT = process.env.RIVET_ENDPOINT; -const RIVET_SERVICE_TOKEN = process.env.RIVET_SERVICE_TOKEN; -const RIVET_PROJECT = process.env.RIVET_PROJECT; -const RIVET_ENVIRONMENT = process.env.RIVET_ENVIRONMENT; - -// Determine test kind from environment variable -const BUILD_NAME = process.env.BUILD; -if (BUILD_NAME !== "ws-isolate" && BUILD_NAME !== "ws-container") { - throw new Error( - "Must specify BUILD environment variable as either 'ws-isolate' or 'ws-container'", - ); -} - -let region = process.env.REGION; -if (!region || region.length === 0) { - region = undefined; -} - -const client = new RivetClient({ - environment: RIVET_ENDPOINT, - token: RIVET_SERVICE_TOKEN, -}); - -async function run() { - let actorId: string | undefined; - try { - console.time(`create actor`); - console.log("Creating actor", { region }); - const { actor } = await client.actor.create({ - project: RIVET_PROJECT, - environment: RIVET_ENVIRONMENT, - body: { - region, - tags: { - name: BUILD_NAME, - }, - buildTags: { name: BUILD_NAME, current: "true" }, - network: { - ports: { - http: { - protocol: "https", - // internalPort: 80, - routing: { - guard: {}, - }, - }, - udp: { - protocol: "udp", - // internalPort: 80, - routing: { - host: {}, - }, - }, - }, - }, - lifecycle: { - durable: false, - }, - ...(BUILD_NAME === "ws-container" - ? { - resources: { - cpu: 100, - memory: 100, - }, - } - : {}), - }, - }); - actorId = actor.id; - - console.timeEnd(`create actor`); - - const port = actor.network.ports.http; - - const actorOrigin = `${port.protocol}://${port.hostname}:${port.port}${port.path ?? ""}`; - console.log("Created actor at", actorOrigin); - - //await new Promise((resolve) => setTimeout(resolve, 300)); - - //console.time(`ready-${actorId}`); - //while (true) { - // // Check HTTP health of service - // const response = await fetch(`${actorOrigin}/health`); - // if (!response.ok) { - // await new Promise(resolve => setTimeout(resolve, 100)); - // continue; - // } - // console.timeEnd(`ready-${actorId}`); - // break; - //} - - // Retry loop for HTTP health check - console.time(`ready ${actorId}`); - while (true) { - try { - const response = await fetch(`${actorOrigin}/health`); - if (response.ok) { - console.log("Health check passed"); - console.timeEnd(`ready ${actorId}`); - break; - } else { - console.error( - `Health check failed with status: ${response.status}, retrying...`, - ); - } - } catch (error) { - console.error("Health check request error:", error); - } - await new Promise((resolve) => setTimeout(resolve, 100)); - } - - // WS - await new Promise((resolve, reject) => { - // Open a WebSocket to that endpoint - const ws = new WebSocket(`${actorOrigin}/ws`); - - ws.onmessage = (evt) => { - const [type, body] = JSON.parse(evt.data as any); - if (type === "init") { - console.log("Init event data:", body); - } else if (type === "pong") { - console.log("Pong"); - ws.close(); - resolve(undefined); - } else { - console.warn("unknown message type", type); - } - }; - - ws.onopen = () => { - console.log("Ping"); - ws.send(JSON.stringify(["ping", 123])); - }; - - ws.onclose = (ev) => { - if (ev.wasClean) { - console.log("WebSocket connection closed"); - } else { - reject( - `WebSocket did not close cleanly: ${ev.reason} ${ev.code}`, - ); - } - }; - - ws.onerror = (err) => { - console.error("WS error", err); - reject("ws error"); - }; - }); - - // UDP - const res = await client.actor.get(actor.id, { - project: RIVET_PROJECT, - environment: RIVET_ENVIRONMENT, - }); - - console.log("Connecting to UDP echo server..."); - const udpPort = res.actor.network.ports.udp; - const udpServer = `${udpPort.hostname}:${udpPort.port}`; - console.log("UDP server address:", udpServer); - - // Create a UDP socket - const udpClient = dgram.createSocket("udp4"); - - // Send a message to the UDP echo server - const message = Buffer.from("Hello UDP server!"); - udpClient.send(message, udpPort.port, udpPort.hostname, (err) => { - if (err) { - console.error("Error sending UDP message:", err); - udpClient.close(); - } else { - console.log("UDP message sent"); - } - }); - - // Listen for a response - udpClient.on("message", (msg, rinfo) => { - console.log(`UDP message received: ${msg.toString()}`); - console.log(`From: ${rinfo.address}:${rinfo.port}`); - udpClient.close(); - }); - - udpClient.on("error", (err) => { - console.error("UDP client error:", err); - udpClient.close(); - }); - - udpClient.on("close", () => { - console.log("UDP connection closed"); - }); - - // await client.actor.upgrade(actor.id, { - // project: RIVET_PROJECT, - // environment: RIVET_ENVIRONMENT, - // body: { - // buildTags: { name: BUILD_NAME, current: "true" }, - // } - // }); - - console.log("Sleeping forever so you can debug"); - await new Promise((resolve) => setTimeout(resolve, 100_000_000)); - } catch (error) { - console.error("Error:", error); - } finally { - if (actorId) { - console.log("Destroying", actorId); - await client.actor.destroy(actorId, { - project: RIVET_PROJECT, - environment: RIVET_ENVIRONMENT, - }); - } - } -} - -async function runLoop() { - while (true) { - await run(); - await new Promise((resolve) => - setTimeout(resolve, Math.random() * 250), - ); - } -} - -// Run loop without top-level await -(async () => { - for (let i = 0; i < 1; i++) { - await new Promise((resolve) => setTimeout(resolve, 100)); - runLoop(); - } -})(); diff --git a/examples/system-test-actor/tsconfig.json b/examples/system-test-actor/tsconfig.json deleted file mode 100644 index f5113240c4..0000000000 --- a/examples/system-test-actor/tsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "module": "NodeNext", - "moduleResolution": "NodeNext", - "types": ["node", "deno"], - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - "isolatedModules": true, - "strict": true, - "skipLibCheck": true, - "outDir": "dist" - }, - "include": ["**/*.ts"], - "exclude": ["node_modules", "dist"] -} diff --git a/examples/system-test-actor/yarn.lock b/examples/system-test-actor/yarn.lock deleted file mode 100644 index dca9c217be..0000000000 --- a/examples/system-test-actor/yarn.lock +++ /dev/null @@ -1,1739 +0,0 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 8 - cacheKey: 10c0 - -"@esbuild/aix-ppc64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/aix-ppc64@npm:0.25.0" - conditions: os=aix & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/android-arm64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/android-arm64@npm:0.25.0" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/android-arm@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/android-arm@npm:0.25.0" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - -"@esbuild/android-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/android-x64@npm:0.25.0" - conditions: os=android & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/darwin-arm64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/darwin-arm64@npm:0.25.0" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/darwin-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/darwin-x64@npm:0.25.0" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/freebsd-arm64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/freebsd-arm64@npm:0.25.0" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/freebsd-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/freebsd-x64@npm:0.25.0" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/linux-arm64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-arm64@npm:0.25.0" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/linux-arm@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-arm@npm:0.25.0" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@esbuild/linux-ia32@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-ia32@npm:0.25.0" - conditions: os=linux & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/linux-loong64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-loong64@npm:0.25.0" - conditions: os=linux & cpu=loong64 - languageName: node - linkType: hard - -"@esbuild/linux-mips64el@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-mips64el@npm:0.25.0" - conditions: os=linux & cpu=mips64el - languageName: node - linkType: hard - -"@esbuild/linux-ppc64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-ppc64@npm:0.25.0" - conditions: os=linux & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/linux-riscv64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-riscv64@npm:0.25.0" - conditions: os=linux & cpu=riscv64 - languageName: node - linkType: hard - -"@esbuild/linux-s390x@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-s390x@npm:0.25.0" - conditions: os=linux & cpu=s390x - languageName: node - linkType: hard - -"@esbuild/linux-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-x64@npm:0.25.0" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/netbsd-arm64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/netbsd-arm64@npm:0.25.0" - conditions: os=netbsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/netbsd-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/netbsd-x64@npm:0.25.0" - conditions: os=netbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/openbsd-arm64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/openbsd-arm64@npm:0.25.0" - conditions: os=openbsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/openbsd-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/openbsd-x64@npm:0.25.0" - conditions: os=openbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/sunos-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/sunos-x64@npm:0.25.0" - conditions: os=sunos & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/win32-arm64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/win32-arm64@npm:0.25.0" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/win32-ia32@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/win32-ia32@npm:0.25.0" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/win32-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/win32-x64@npm:0.25.0" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@hono/node-server@npm:^1.13.8": - version: 1.13.8 - resolution: "@hono/node-server@npm:1.13.8" - peerDependencies: - hono: ^4 - checksum: 10c0/5880892fddc2e3272886b3158a278baf3d054d5772bbe98bb71d5eb1c6030900653c7445221ad4de688527522d782ac5924fb27f944d76fad0cdf7d48ca030d0 - languageName: node - linkType: hard - -"@hono/node-ws@npm:^1.1.0": - version: 1.1.0 - resolution: "@hono/node-ws@npm:1.1.0" - dependencies: - ws: "npm:^8.17.0" - peerDependencies: - "@hono/node-server": ^1.11.1 - hono: ^4.6.0 - checksum: 10c0/08e3aadfcab61c45d394e0c4f12d1923bb3e2e68fe86ab96efe15e90caa18bd8d914f9e2a0abbc5547c8a5f78d36c3dc61093b2171079ebee7641ff3cdce7636 - languageName: node - linkType: hard - -"@isaacs/cliui@npm:^8.0.2": - version: 8.0.2 - resolution: "@isaacs/cliui@npm:8.0.2" - dependencies: - string-width: "npm:^5.1.2" - string-width-cjs: "npm:string-width@^4.2.0" - strip-ansi: "npm:^7.0.1" - strip-ansi-cjs: "npm:strip-ansi@^6.0.1" - wrap-ansi: "npm:^8.1.0" - wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" - checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e - languageName: node - linkType: hard - -"@isaacs/fs-minipass@npm:^4.0.0": - version: 4.0.1 - resolution: "@isaacs/fs-minipass@npm:4.0.1" - dependencies: - minipass: "npm:^7.0.4" - checksum: 10c0/c25b6dc1598790d5b55c0947a9b7d111cfa92594db5296c3b907e2f533c033666f692a3939eadac17b1c7c40d362d0b0635dc874cbfe3e70db7c2b07cc97a5d2 - languageName: node - linkType: hard - -"@npmcli/agent@npm:^3.0.0": - version: 3.0.0 - resolution: "@npmcli/agent@npm:3.0.0" - dependencies: - agent-base: "npm:^7.1.0" - http-proxy-agent: "npm:^7.0.0" - https-proxy-agent: "npm:^7.0.1" - lru-cache: "npm:^10.0.1" - socks-proxy-agent: "npm:^8.0.3" - checksum: 10c0/efe37b982f30740ee77696a80c196912c274ecd2cb243bc6ae7053a50c733ce0f6c09fda085145f33ecf453be19654acca74b69e81eaad4c90f00ccffe2f9271 - languageName: node - linkType: hard - -"@npmcli/fs@npm:^4.0.0": - version: 4.0.0 - resolution: "@npmcli/fs@npm:4.0.0" - dependencies: - semver: "npm:^7.3.5" - checksum: 10c0/c90935d5ce670c87b6b14fab04a965a3b8137e585f8b2a6257263bd7f97756dd736cb165bb470e5156a9e718ecd99413dccc54b1138c1a46d6ec7cf325982fe5 - languageName: node - linkType: hard - -"@pkgjs/parseargs@npm:^0.11.0": - version: 0.11.0 - resolution: "@pkgjs/parseargs@npm:0.11.0" - checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd - languageName: node - linkType: hard - -"@rivet-gg/actor-core@npm:^5.1.2": - version: 5.1.3 - resolution: "@rivet-gg/actor-core@npm:5.1.3" - dependencies: - zod: "npm:^3.24.1" - checksum: 10c0/9723a95f2fc0701b8ebe2743378d49d9b37ffc8055cbdbf8dd7ff3ba40484c4b7e0c20caa3d34e1aed07d0a96adf654d417593fae2d01204d34bbe2a09f51a1d - languageName: node - linkType: hard - -"@rivet-gg/api@npm:^24.6.2": - version: 24.6.2 - resolution: "@rivet-gg/api@npm:24.6.2" - dependencies: - "@types/readable-stream": "npm:^4.0.18" - form-data: "npm:^4.0.0" - js-base64: "npm:^3.7.5" - node-fetch: "npm:2" - qs: "npm:^6.11.2" - readable-stream: "npm:^4.5.2" - url-join: "npm:^5.0.0" - checksum: 10c0/5c3355516f69daf3e46550d5e7ba0774a7ab8943a828f60e03b9a5c534000df61e68f9450b47aa739ce28600b5b5d40045ab86df6f3ca0c49f30929382cc667c - languageName: node - linkType: hard - -"@types/deno@npm:^2.2.0": - version: 2.2.0 - resolution: "@types/deno@npm:2.2.0" - checksum: 10c0/cb45bbffe66a3008224a509c6bcb338921cc68b9045363f77ba5d84650d879b8fd4c810db24369a93fbce4a8e2855808bb141c0447feb47d911a7512ba374bde - languageName: node - linkType: hard - -"@types/node@npm:*, @types/node@npm:^22.13.9": - version: 22.13.9 - resolution: "@types/node@npm:22.13.9" - dependencies: - undici-types: "npm:~6.20.0" - checksum: 10c0/eb6acd04169a076631dcaab712128d492cd17a1b3f10daae4a377f3d439c860c3cd3e32f4ef221671f56183b976ac7c4089f4193457314a88675ead4663438a4 - languageName: node - linkType: hard - -"@types/readable-stream@npm:^4.0.18": - version: 4.0.18 - resolution: "@types/readable-stream@npm:4.0.18" - dependencies: - "@types/node": "npm:*" - safe-buffer: "npm:~5.1.1" - checksum: 10c0/641e0e91b9ecfeed72f7509089f25923e06e19e79ed36f962785c41c07b0c9ecb2ecfdf6d290a101b9b5a669a3b89ee3aff0cad57b66a05e2a30cd199052e3e1 - languageName: node - linkType: hard - -"@types/ws@npm:^8.18.0": - version: 8.18.0 - resolution: "@types/ws@npm:8.18.0" - dependencies: - "@types/node": "npm:*" - checksum: 10c0/a56d2e0d1da7411a1f3548ce02b51a50cbe9e23f025677d03df48f87e4a3c72e1342fbf1d12e487d7eafa8dc670c605152b61bbf9165891ec0e9694b0d3ea8d4 - languageName: node - linkType: hard - -"abbrev@npm:^3.0.0": - version: 3.0.0 - resolution: "abbrev@npm:3.0.0" - checksum: 10c0/049704186396f571650eb7b22ed3627b77a5aedf98bb83caf2eac81ca2a3e25e795394b0464cfb2d6076df3db6a5312139eac5b6a126ca296ac53c5008069c28 - languageName: node - linkType: hard - -"abort-controller@npm:^3.0.0": - version: 3.0.0 - resolution: "abort-controller@npm:3.0.0" - dependencies: - event-target-shim: "npm:^5.0.0" - checksum: 10c0/90ccc50f010250152509a344eb2e71977fbf8db0ab8f1061197e3275ddf6c61a41a6edfd7b9409c664513131dd96e962065415325ef23efa5db931b382d24ca5 - languageName: node - linkType: hard - -"agent-base@npm:^7.1.0, agent-base@npm:^7.1.2": - version: 7.1.3 - resolution: "agent-base@npm:7.1.3" - checksum: 10c0/6192b580c5b1d8fb399b9c62bf8343d76654c2dd62afcb9a52b2cf44a8b6ace1e3b704d3fe3547d91555c857d3df02603341ff2cb961b9cfe2b12f9f3c38ee11 - languageName: node - linkType: hard - -"ansi-regex@npm:^5.0.1": - version: 5.0.1 - resolution: "ansi-regex@npm:5.0.1" - checksum: 10c0/9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737 - languageName: node - linkType: hard - -"ansi-regex@npm:^6.0.1": - version: 6.1.0 - resolution: "ansi-regex@npm:6.1.0" - checksum: 10c0/a91daeddd54746338478eef88af3439a7edf30f8e23196e2d6ed182da9add559c601266dbef01c2efa46a958ad6f1f8b176799657616c702b5b02e799e7fd8dc - languageName: node - linkType: hard - -"ansi-styles@npm:^4.0.0": - version: 4.3.0 - resolution: "ansi-styles@npm:4.3.0" - dependencies: - color-convert: "npm:^2.0.1" - checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 - languageName: node - linkType: hard - -"ansi-styles@npm:^6.1.0": - version: 6.2.1 - resolution: "ansi-styles@npm:6.2.1" - checksum: 10c0/5d1ec38c123984bcedd996eac680d548f31828bd679a66db2bdf11844634dde55fec3efa9c6bb1d89056a5e79c1ac540c4c784d592ea1d25028a92227d2f2d5c - languageName: node - linkType: hard - -"asynckit@npm:^0.4.0": - version: 0.4.0 - resolution: "asynckit@npm:0.4.0" - checksum: 10c0/d73e2ddf20c4eb9337e1b3df1a0f6159481050a5de457c55b14ea2e5cb6d90bb69e004c9af54737a5ee0917fcf2c9e25de67777bbe58261847846066ba75bc9d - languageName: node - linkType: hard - -"balanced-match@npm:^1.0.0": - version: 1.0.2 - resolution: "balanced-match@npm:1.0.2" - checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee - languageName: node - linkType: hard - -"base64-js@npm:^1.3.1": - version: 1.5.1 - resolution: "base64-js@npm:1.5.1" - checksum: 10c0/f23823513b63173a001030fae4f2dabe283b99a9d324ade3ad3d148e218134676f1ee8568c877cd79ec1c53158dcf2d2ba527a97c606618928ba99dd930102bf - languageName: node - linkType: hard - -"brace-expansion@npm:^2.0.1": - version: 2.0.1 - resolution: "brace-expansion@npm:2.0.1" - dependencies: - balanced-match: "npm:^1.0.0" - checksum: 10c0/b358f2fe060e2d7a87aa015979ecea07f3c37d4018f8d6deb5bd4c229ad3a0384fe6029bb76cd8be63c81e516ee52d1a0673edbe2023d53a5191732ae3c3e49f - languageName: node - linkType: hard - -"buffer@npm:^6.0.3": - version: 6.0.3 - resolution: "buffer@npm:6.0.3" - dependencies: - base64-js: "npm:^1.3.1" - ieee754: "npm:^1.2.1" - checksum: 10c0/2a905fbbcde73cc5d8bd18d1caa23715d5f83a5935867c2329f0ac06104204ba7947be098fe1317fbd8830e26090ff8e764f08cd14fefc977bb248c3487bcbd0 - languageName: node - linkType: hard - -"cacache@npm:^19.0.1": - version: 19.0.1 - resolution: "cacache@npm:19.0.1" - dependencies: - "@npmcli/fs": "npm:^4.0.0" - fs-minipass: "npm:^3.0.0" - glob: "npm:^10.2.2" - lru-cache: "npm:^10.0.1" - minipass: "npm:^7.0.3" - minipass-collect: "npm:^2.0.1" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.4" - p-map: "npm:^7.0.2" - ssri: "npm:^12.0.0" - tar: "npm:^7.4.3" - unique-filename: "npm:^4.0.0" - checksum: 10c0/01f2134e1bd7d3ab68be851df96c8d63b492b1853b67f2eecb2c37bb682d37cb70bb858a16f2f0554d3c0071be6dfe21456a1ff6fa4b7eed996570d6a25ffe9c - languageName: node - linkType: hard - -"call-bind-apply-helpers@npm:^1.0.1, call-bind-apply-helpers@npm:^1.0.2": - version: 1.0.2 - resolution: "call-bind-apply-helpers@npm:1.0.2" - dependencies: - es-errors: "npm:^1.3.0" - function-bind: "npm:^1.1.2" - checksum: 10c0/47bd9901d57b857590431243fea704ff18078b16890a6b3e021e12d279bbf211d039155e27d7566b374d49ee1f8189344bac9833dec7a20cdec370506361c938 - languageName: node - linkType: hard - -"call-bound@npm:^1.0.2": - version: 1.0.4 - resolution: "call-bound@npm:1.0.4" - dependencies: - call-bind-apply-helpers: "npm:^1.0.2" - get-intrinsic: "npm:^1.3.0" - checksum: 10c0/f4796a6a0941e71c766aea672f63b72bc61234c4f4964dc6d7606e3664c307e7d77845328a8f3359ce39ddb377fed67318f9ee203dea1d47e46165dcf2917644 - languageName: node - linkType: hard - -"chownr@npm:^3.0.0": - version: 3.0.0 - resolution: "chownr@npm:3.0.0" - checksum: 10c0/43925b87700f7e3893296c8e9c56cc58f926411cce3a6e5898136daaf08f08b9a8eb76d37d3267e707d0dcc17aed2e2ebdf5848c0c3ce95cf910a919935c1b10 - languageName: node - linkType: hard - -"color-convert@npm:^2.0.1": - version: 2.0.1 - resolution: "color-convert@npm:2.0.1" - dependencies: - color-name: "npm:~1.1.4" - checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 - languageName: node - linkType: hard - -"color-name@npm:~1.1.4": - version: 1.1.4 - resolution: "color-name@npm:1.1.4" - checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 - languageName: node - linkType: hard - -"combined-stream@npm:^1.0.8": - version: 1.0.8 - resolution: "combined-stream@npm:1.0.8" - dependencies: - delayed-stream: "npm:~1.0.0" - checksum: 10c0/0dbb829577e1b1e839fa82b40c07ffaf7de8a09b935cadd355a73652ae70a88b4320db322f6634a4ad93424292fa80973ac6480986247f1734a1137debf271d5 - languageName: node - linkType: hard - -"cross-spawn@npm:^7.0.6": - version: 7.0.6 - resolution: "cross-spawn@npm:7.0.6" - dependencies: - path-key: "npm:^3.1.0" - shebang-command: "npm:^2.0.0" - which: "npm:^2.0.1" - checksum: 10c0/053ea8b2135caff68a9e81470e845613e374e7309a47731e81639de3eaeb90c3d01af0e0b44d2ab9d50b43467223b88567dfeb3262db942dc063b9976718ffc1 - languageName: node - linkType: hard - -"data-uri-to-buffer@npm:^4.0.0": - version: 4.0.1 - resolution: "data-uri-to-buffer@npm:4.0.1" - checksum: 10c0/20a6b93107597530d71d4cb285acee17f66bcdfc03fd81040921a81252f19db27588d87fc8fc69e1950c55cfb0bf8ae40d0e5e21d907230813eb5d5a7f9eb45b - languageName: node - linkType: hard - -"debug@npm:4, debug@npm:^4.3.4": - version: 4.4.0 - resolution: "debug@npm:4.4.0" - dependencies: - ms: "npm:^2.1.3" - peerDependenciesMeta: - supports-color: - optional: true - checksum: 10c0/db94f1a182bf886f57b4755f85b3a74c39b5114b9377b7ab375dc2cfa3454f09490cc6c30f829df3fc8042bc8b8995f6567ce5cd96f3bc3688bd24027197d9de - languageName: node - linkType: hard - -"delayed-stream@npm:~1.0.0": - version: 1.0.0 - resolution: "delayed-stream@npm:1.0.0" - checksum: 10c0/d758899da03392e6712f042bec80aa293bbe9e9ff1b2634baae6a360113e708b91326594c8a486d475c69d6259afb7efacdc3537bfcda1c6c648e390ce601b19 - languageName: node - linkType: hard - -"dgram@npm:^1.0.1": - version: 1.0.1 - resolution: "dgram@npm:1.0.1" - checksum: 10c0/de7db34827917ee4f2a8ba113b2e07b38d992feaa369cc539b8ac116d81c69feadf2f9f510dae7d58342c88af6330022ad0445fda1eafe6b9017ad9ffd6a28f4 - languageName: node - linkType: hard - -"dunder-proto@npm:^1.0.1": - version: 1.0.1 - resolution: "dunder-proto@npm:1.0.1" - dependencies: - call-bind-apply-helpers: "npm:^1.0.1" - es-errors: "npm:^1.3.0" - gopd: "npm:^1.2.0" - checksum: 10c0/199f2a0c1c16593ca0a145dbf76a962f8033ce3129f01284d48c45ed4e14fea9bbacd7b3610b6cdc33486cef20385ac054948fefc6272fcce645c09468f93031 - languageName: node - linkType: hard - -"eastasianwidth@npm:^0.2.0": - version: 0.2.0 - resolution: "eastasianwidth@npm:0.2.0" - checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 - languageName: node - linkType: hard - -"emoji-regex@npm:^8.0.0": - version: 8.0.0 - resolution: "emoji-regex@npm:8.0.0" - checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 - languageName: node - linkType: hard - -"emoji-regex@npm:^9.2.2": - version: 9.2.2 - resolution: "emoji-regex@npm:9.2.2" - checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 - languageName: node - linkType: hard - -"encoding@npm:^0.1.13": - version: 0.1.13 - resolution: "encoding@npm:0.1.13" - dependencies: - iconv-lite: "npm:^0.6.2" - checksum: 10c0/36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039 - languageName: node - linkType: hard - -"env-paths@npm:^2.2.0": - version: 2.2.1 - resolution: "env-paths@npm:2.2.1" - checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 - languageName: node - linkType: hard - -"err-code@npm:^2.0.2": - version: 2.0.3 - resolution: "err-code@npm:2.0.3" - checksum: 10c0/b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66 - languageName: node - linkType: hard - -"es-define-property@npm:^1.0.1": - version: 1.0.1 - resolution: "es-define-property@npm:1.0.1" - checksum: 10c0/3f54eb49c16c18707949ff25a1456728c883e81259f045003499efba399c08bad00deebf65cccde8c0e07908c1a225c9d472b7107e558f2a48e28d530e34527c - languageName: node - linkType: hard - -"es-errors@npm:^1.3.0": - version: 1.3.0 - resolution: "es-errors@npm:1.3.0" - checksum: 10c0/0a61325670072f98d8ae3b914edab3559b6caa980f08054a3b872052640d91da01d38df55df797fcc916389d77fc92b8d5906cf028f4db46d7e3003abecbca85 - languageName: node - linkType: hard - -"es-object-atoms@npm:^1.0.0, es-object-atoms@npm:^1.1.1": - version: 1.1.1 - resolution: "es-object-atoms@npm:1.1.1" - dependencies: - es-errors: "npm:^1.3.0" - checksum: 10c0/65364812ca4daf48eb76e2a3b7a89b3f6a2e62a1c420766ce9f692665a29d94fe41fe88b65f24106f449859549711e4b40d9fb8002d862dfd7eb1c512d10be0c - languageName: node - linkType: hard - -"es-set-tostringtag@npm:^2.1.0": - version: 2.1.0 - resolution: "es-set-tostringtag@npm:2.1.0" - dependencies: - es-errors: "npm:^1.3.0" - get-intrinsic: "npm:^1.2.6" - has-tostringtag: "npm:^1.0.2" - hasown: "npm:^2.0.2" - checksum: 10c0/ef2ca9ce49afe3931cb32e35da4dcb6d86ab02592cfc2ce3e49ced199d9d0bb5085fc7e73e06312213765f5efa47cc1df553a6a5154584b21448e9fb8355b1af - languageName: node - linkType: hard - -"esbuild@npm:~0.25.0": - version: 0.25.0 - resolution: "esbuild@npm:0.25.0" - dependencies: - "@esbuild/aix-ppc64": "npm:0.25.0" - "@esbuild/android-arm": "npm:0.25.0" - "@esbuild/android-arm64": "npm:0.25.0" - "@esbuild/android-x64": "npm:0.25.0" - "@esbuild/darwin-arm64": "npm:0.25.0" - "@esbuild/darwin-x64": "npm:0.25.0" - "@esbuild/freebsd-arm64": "npm:0.25.0" - "@esbuild/freebsd-x64": "npm:0.25.0" - "@esbuild/linux-arm": "npm:0.25.0" - "@esbuild/linux-arm64": "npm:0.25.0" - "@esbuild/linux-ia32": "npm:0.25.0" - "@esbuild/linux-loong64": "npm:0.25.0" - "@esbuild/linux-mips64el": "npm:0.25.0" - "@esbuild/linux-ppc64": "npm:0.25.0" - "@esbuild/linux-riscv64": "npm:0.25.0" - "@esbuild/linux-s390x": "npm:0.25.0" - "@esbuild/linux-x64": "npm:0.25.0" - "@esbuild/netbsd-arm64": "npm:0.25.0" - "@esbuild/netbsd-x64": "npm:0.25.0" - "@esbuild/openbsd-arm64": "npm:0.25.0" - "@esbuild/openbsd-x64": "npm:0.25.0" - "@esbuild/sunos-x64": "npm:0.25.0" - "@esbuild/win32-arm64": "npm:0.25.0" - "@esbuild/win32-ia32": "npm:0.25.0" - "@esbuild/win32-x64": "npm:0.25.0" - dependenciesMeta: - "@esbuild/aix-ppc64": - optional: true - "@esbuild/android-arm": - optional: true - "@esbuild/android-arm64": - optional: true - "@esbuild/android-x64": - optional: true - "@esbuild/darwin-arm64": - optional: true - "@esbuild/darwin-x64": - optional: true - "@esbuild/freebsd-arm64": - optional: true - "@esbuild/freebsd-x64": - optional: true - "@esbuild/linux-arm": - optional: true - "@esbuild/linux-arm64": - optional: true - "@esbuild/linux-ia32": - optional: true - "@esbuild/linux-loong64": - optional: true - "@esbuild/linux-mips64el": - optional: true - "@esbuild/linux-ppc64": - optional: true - "@esbuild/linux-riscv64": - optional: true - "@esbuild/linux-s390x": - optional: true - "@esbuild/linux-x64": - optional: true - "@esbuild/netbsd-arm64": - optional: true - "@esbuild/netbsd-x64": - optional: true - "@esbuild/openbsd-arm64": - optional: true - "@esbuild/openbsd-x64": - optional: true - "@esbuild/sunos-x64": - optional: true - "@esbuild/win32-arm64": - optional: true - "@esbuild/win32-ia32": - optional: true - "@esbuild/win32-x64": - optional: true - bin: - esbuild: bin/esbuild - checksum: 10c0/5767b72da46da3cfec51661647ec850ddbf8a8d0662771139f10ef0692a8831396a0004b2be7966cecdb08264fb16bdc16290dcecd92396fac5f12d722fa013d - languageName: node - linkType: hard - -"event-target-shim@npm:^5.0.0": - version: 5.0.1 - resolution: "event-target-shim@npm:5.0.1" - checksum: 10c0/0255d9f936215fd206156fd4caa9e8d35e62075d720dc7d847e89b417e5e62cf1ce6c9b4e0a1633a9256de0efefaf9f8d26924b1f3c8620cffb9db78e7d3076b - languageName: node - linkType: hard - -"events@npm:^3.3.0": - version: 3.3.0 - resolution: "events@npm:3.3.0" - checksum: 10c0/d6b6f2adbccbcda74ddbab52ed07db727ef52e31a61ed26db9feb7dc62af7fc8e060defa65e5f8af9449b86b52cc1a1f6a79f2eafcf4e62add2b7a1fa4a432f6 - languageName: node - linkType: hard - -"exponential-backoff@npm:^3.1.1": - version: 3.1.2 - resolution: "exponential-backoff@npm:3.1.2" - checksum: 10c0/d9d3e1eafa21b78464297df91f1776f7fbaa3d5e3f7f0995648ca5b89c069d17055033817348d9f4a43d1c20b0eab84f75af6991751e839df53e4dfd6f22e844 - languageName: node - linkType: hard - -"fetch-blob@npm:^3.1.2, fetch-blob@npm:^3.1.4": - version: 3.2.0 - resolution: "fetch-blob@npm:3.2.0" - dependencies: - node-domexception: "npm:^1.0.0" - web-streams-polyfill: "npm:^3.0.3" - checksum: 10c0/60054bf47bfa10fb0ba6cb7742acec2f37c1f56344f79a70bb8b1c48d77675927c720ff3191fa546410a0442c998d27ab05e9144c32d530d8a52fbe68f843b69 - languageName: node - linkType: hard - -"foreground-child@npm:^3.1.0": - version: 3.3.1 - resolution: "foreground-child@npm:3.3.1" - dependencies: - cross-spawn: "npm:^7.0.6" - signal-exit: "npm:^4.0.1" - checksum: 10c0/8986e4af2430896e65bc2788d6679067294d6aee9545daefc84923a0a4b399ad9c7a3ea7bd8c0b2b80fdf4a92de4c69df3f628233ff3224260e9c1541a9e9ed3 - languageName: node - linkType: hard - -"form-data@npm:^4.0.0": - version: 4.0.2 - resolution: "form-data@npm:4.0.2" - dependencies: - asynckit: "npm:^0.4.0" - combined-stream: "npm:^1.0.8" - es-set-tostringtag: "npm:^2.1.0" - mime-types: "npm:^2.1.12" - checksum: 10c0/e534b0cf025c831a0929bf4b9bbe1a9a6b03e273a8161f9947286b9b13bf8fb279c6944aae0070c4c311100c6d6dbb815cd955dc217728caf73fad8dc5b8ee9c - languageName: node - linkType: hard - -"formdata-polyfill@npm:^4.0.10": - version: 4.0.10 - resolution: "formdata-polyfill@npm:4.0.10" - dependencies: - fetch-blob: "npm:^3.1.2" - checksum: 10c0/5392ec484f9ce0d5e0d52fb5a78e7486637d516179b0eb84d81389d7eccf9ca2f663079da56f761355c0a65792810e3b345dc24db9a8bbbcf24ef3c8c88570c6 - languageName: node - linkType: hard - -"fs-minipass@npm:^3.0.0": - version: 3.0.3 - resolution: "fs-minipass@npm:3.0.3" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94 - languageName: node - linkType: hard - -"fsevents@npm:~2.3.3": - version: 2.3.3 - resolution: "fsevents@npm:2.3.3" - dependencies: - node-gyp: "npm:latest" - checksum: 10c0/a1f0c44595123ed717febbc478aa952e47adfc28e2092be66b8ab1635147254ca6cfe1df792a8997f22716d4cbafc73309899ff7bfac2ac3ad8cf2e4ecc3ec60 - conditions: os=darwin - languageName: node - linkType: hard - -"fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": - version: 2.3.3 - resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" - dependencies: - node-gyp: "npm:latest" - conditions: os=darwin - languageName: node - linkType: hard - -"function-bind@npm:^1.1.2": - version: 1.1.2 - resolution: "function-bind@npm:1.1.2" - checksum: 10c0/d8680ee1e5fcd4c197e4ac33b2b4dce03c71f4d91717292785703db200f5c21f977c568d28061226f9b5900cbcd2c84463646134fd5337e7925e0942bc3f46d5 - languageName: node - linkType: hard - -"get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.3.0": - version: 1.3.0 - resolution: "get-intrinsic@npm:1.3.0" - dependencies: - call-bind-apply-helpers: "npm:^1.0.2" - es-define-property: "npm:^1.0.1" - es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.1.1" - function-bind: "npm:^1.1.2" - get-proto: "npm:^1.0.1" - gopd: "npm:^1.2.0" - has-symbols: "npm:^1.1.0" - hasown: "npm:^2.0.2" - math-intrinsics: "npm:^1.1.0" - checksum: 10c0/52c81808af9a8130f581e6a6a83e1ba4a9f703359e7a438d1369a5267a25412322f03dcbd7c549edaef0b6214a0630a28511d7df0130c93cfd380f4fa0b5b66a - languageName: node - linkType: hard - -"get-proto@npm:^1.0.1": - version: 1.0.1 - resolution: "get-proto@npm:1.0.1" - dependencies: - dunder-proto: "npm:^1.0.1" - es-object-atoms: "npm:^1.0.0" - checksum: 10c0/9224acb44603c5526955e83510b9da41baf6ae73f7398875fba50edc5e944223a89c4a72b070fcd78beb5f7bdda58ecb6294adc28f7acfc0da05f76a2399643c - languageName: node - linkType: hard - -"get-tsconfig@npm:^4.7.5": - version: 4.10.0 - resolution: "get-tsconfig@npm:4.10.0" - dependencies: - resolve-pkg-maps: "npm:^1.0.0" - checksum: 10c0/c9b5572c5118923c491c04285c73bd55b19e214992af957c502a3be0fc0043bb421386ffd45ca3433c0a7fba81221ca300479e8393960acf15d0ed4563f38a86 - languageName: node - linkType: hard - -"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": - version: 10.4.5 - resolution: "glob@npm:10.4.5" - dependencies: - foreground-child: "npm:^3.1.0" - jackspeak: "npm:^3.1.2" - minimatch: "npm:^9.0.4" - minipass: "npm:^7.1.2" - package-json-from-dist: "npm:^1.0.0" - path-scurry: "npm:^1.11.1" - bin: - glob: dist/esm/bin.mjs - checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e - languageName: node - linkType: hard - -"gopd@npm:^1.2.0": - version: 1.2.0 - resolution: "gopd@npm:1.2.0" - checksum: 10c0/50fff1e04ba2b7737c097358534eacadad1e68d24cccee3272e04e007bed008e68d2614f3987788428fd192a5ae3889d08fb2331417e4fc4a9ab366b2043cead - languageName: node - linkType: hard - -"graceful-fs@npm:^4.2.6": - version: 4.2.11 - resolution: "graceful-fs@npm:4.2.11" - checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 - languageName: node - linkType: hard - -"has-symbols@npm:^1.0.3, has-symbols@npm:^1.1.0": - version: 1.1.0 - resolution: "has-symbols@npm:1.1.0" - checksum: 10c0/dde0a734b17ae51e84b10986e651c664379018d10b91b6b0e9b293eddb32f0f069688c841fb40f19e9611546130153e0a2a48fd7f512891fb000ddfa36f5a20e - languageName: node - linkType: hard - -"has-tostringtag@npm:^1.0.2": - version: 1.0.2 - resolution: "has-tostringtag@npm:1.0.2" - dependencies: - has-symbols: "npm:^1.0.3" - checksum: 10c0/a8b166462192bafe3d9b6e420a1d581d93dd867adb61be223a17a8d6dad147aa77a8be32c961bb2f27b3ef893cae8d36f564ab651f5e9b7938ae86f74027c48c - languageName: node - linkType: hard - -"hasown@npm:^2.0.2": - version: 2.0.2 - resolution: "hasown@npm:2.0.2" - dependencies: - function-bind: "npm:^1.1.2" - checksum: 10c0/3769d434703b8ac66b209a4cca0737519925bbdb61dd887f93a16372b14694c63ff4e797686d87c90f08168e81082248b9b028bad60d4da9e0d1148766f56eb9 - languageName: node - linkType: hard - -"hono@npm:^4.6.17": - version: 4.7.4 - resolution: "hono@npm:4.7.4" - checksum: 10c0/b189c5b75527a0b2c6669a8b2d46a2c522c9f429c08da801373b13d25b476f20e639f667a9dac2fe42074e9b6f851d542d28026f158c5728b20034b9b0e3e738 - languageName: node - linkType: hard - -"http-cache-semantics@npm:^4.1.1": - version: 4.1.1 - resolution: "http-cache-semantics@npm:4.1.1" - checksum: 10c0/ce1319b8a382eb3cbb4a37c19f6bfe14e5bb5be3d09079e885e8c513ab2d3cd9214902f8a31c9dc4e37022633ceabfc2d697405deeaf1b8f3552bb4ed996fdfc - languageName: node - linkType: hard - -"http-proxy-agent@npm:^7.0.0": - version: 7.0.2 - resolution: "http-proxy-agent@npm:7.0.2" - dependencies: - agent-base: "npm:^7.1.0" - debug: "npm:^4.3.4" - checksum: 10c0/4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921 - languageName: node - linkType: hard - -"https-proxy-agent@npm:^7.0.1": - version: 7.0.6 - resolution: "https-proxy-agent@npm:7.0.6" - dependencies: - agent-base: "npm:^7.1.2" - debug: "npm:4" - checksum: 10c0/f729219bc735edb621fa30e6e84e60ee5d00802b8247aac0d7b79b0bd6d4b3294737a337b93b86a0bd9e68099d031858a39260c976dc14cdbba238ba1f8779ac - languageName: node - linkType: hard - -"iconv-lite@npm:^0.6.2": - version: 0.6.3 - resolution: "iconv-lite@npm:0.6.3" - dependencies: - safer-buffer: "npm:>= 2.1.2 < 3.0.0" - checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 - languageName: node - linkType: hard - -"ieee754@npm:^1.2.1": - version: 1.2.1 - resolution: "ieee754@npm:1.2.1" - checksum: 10c0/b0782ef5e0935b9f12883a2e2aa37baa75da6e66ce6515c168697b42160807d9330de9a32ec1ed73149aea02e0d822e572bca6f1e22bdcbd2149e13b050b17bb - languageName: node - linkType: hard - -"imurmurhash@npm:^0.1.4": - version: 0.1.4 - resolution: "imurmurhash@npm:0.1.4" - checksum: 10c0/8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 - languageName: node - linkType: hard - -"ip-address@npm:^9.0.5": - version: 9.0.5 - resolution: "ip-address@npm:9.0.5" - dependencies: - jsbn: "npm:1.1.0" - sprintf-js: "npm:^1.1.3" - checksum: 10c0/331cd07fafcb3b24100613e4b53e1a2b4feab11e671e655d46dc09ee233da5011284d09ca40c4ecbdfe1d0004f462958675c224a804259f2f78d2465a87824bc - languageName: node - linkType: hard - -"is-fullwidth-code-point@npm:^3.0.0": - version: 3.0.0 - resolution: "is-fullwidth-code-point@npm:3.0.0" - checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc - languageName: node - linkType: hard - -"isexe@npm:^2.0.0": - version: 2.0.0 - resolution: "isexe@npm:2.0.0" - checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d - languageName: node - linkType: hard - -"isexe@npm:^3.1.1": - version: 3.1.1 - resolution: "isexe@npm:3.1.1" - checksum: 10c0/9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7 - languageName: node - linkType: hard - -"jackspeak@npm:^3.1.2": - version: 3.4.3 - resolution: "jackspeak@npm:3.4.3" - dependencies: - "@isaacs/cliui": "npm:^8.0.2" - "@pkgjs/parseargs": "npm:^0.11.0" - dependenciesMeta: - "@pkgjs/parseargs": - optional: true - checksum: 10c0/6acc10d139eaefdbe04d2f679e6191b3abf073f111edf10b1de5302c97ec93fffeb2fdd8681ed17f16268aa9dd4f8c588ed9d1d3bffbbfa6e8bf897cbb3149b9 - languageName: node - linkType: hard - -"js-base64@npm:^3.7.5": - version: 3.7.7 - resolution: "js-base64@npm:3.7.7" - checksum: 10c0/3c905a7e78b601e4751b5e710edd0d6d045ce2d23eb84c9df03515371e1b291edc72808dc91e081cb9855aef6758292a2407006f4608ec3705373dd8baf2f80f - languageName: node - linkType: hard - -"jsbn@npm:1.1.0": - version: 1.1.0 - resolution: "jsbn@npm:1.1.0" - checksum: 10c0/4f907fb78d7b712e11dea8c165fe0921f81a657d3443dde75359ed52eb2b5d33ce6773d97985a089f09a65edd80b11cb75c767b57ba47391fee4c969f7215c96 - languageName: node - linkType: hard - -"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": - version: 10.4.3 - resolution: "lru-cache@npm:10.4.3" - checksum: 10c0/ebd04fbca961e6c1d6c0af3799adcc966a1babe798f685bb84e6599266599cd95d94630b10262f5424539bc4640107e8a33aa28585374abf561d30d16f4b39fb - languageName: node - linkType: hard - -"make-fetch-happen@npm:^14.0.3": - version: 14.0.3 - resolution: "make-fetch-happen@npm:14.0.3" - dependencies: - "@npmcli/agent": "npm:^3.0.0" - cacache: "npm:^19.0.1" - http-cache-semantics: "npm:^4.1.1" - minipass: "npm:^7.0.2" - minipass-fetch: "npm:^4.0.0" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.4" - negotiator: "npm:^1.0.0" - proc-log: "npm:^5.0.0" - promise-retry: "npm:^2.0.1" - ssri: "npm:^12.0.0" - checksum: 10c0/c40efb5e5296e7feb8e37155bde8eb70bc57d731b1f7d90e35a092fde403d7697c56fb49334d92d330d6f1ca29a98142036d6480a12681133a0a1453164cb2f0 - languageName: node - linkType: hard - -"math-intrinsics@npm:^1.1.0": - version: 1.1.0 - resolution: "math-intrinsics@npm:1.1.0" - checksum: 10c0/7579ff94e899e2f76ab64491d76cf606274c874d8f2af4a442c016bd85688927fcfca157ba6bf74b08e9439dc010b248ce05b96cc7c126a354c3bae7fcb48b7f - languageName: node - linkType: hard - -"mime-db@npm:1.52.0": - version: 1.52.0 - resolution: "mime-db@npm:1.52.0" - checksum: 10c0/0557a01deebf45ac5f5777fe7740b2a5c309c6d62d40ceab4e23da9f821899ce7a900b7ac8157d4548ddbb7beffe9abc621250e6d182b0397ec7f10c7b91a5aa - languageName: node - linkType: hard - -"mime-types@npm:^2.1.12": - version: 2.1.35 - resolution: "mime-types@npm:2.1.35" - dependencies: - mime-db: "npm:1.52.0" - checksum: 10c0/82fb07ec56d8ff1fc999a84f2f217aa46cb6ed1033fefaabd5785b9a974ed225c90dc72fff460259e66b95b73648596dbcc50d51ed69cdf464af2d237d3149b2 - languageName: node - linkType: hard - -"minimatch@npm:^9.0.4": - version: 9.0.5 - resolution: "minimatch@npm:9.0.5" - dependencies: - brace-expansion: "npm:^2.0.1" - checksum: 10c0/de96cf5e35bdf0eab3e2c853522f98ffbe9a36c37797778d2665231ec1f20a9447a7e567cb640901f89e4daaa95ae5d70c65a9e8aa2bb0019b6facbc3c0575ed - languageName: node - linkType: hard - -"minipass-collect@npm:^2.0.1": - version: 2.0.1 - resolution: "minipass-collect@npm:2.0.1" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e - languageName: node - linkType: hard - -"minipass-fetch@npm:^4.0.0": - version: 4.0.1 - resolution: "minipass-fetch@npm:4.0.1" - dependencies: - encoding: "npm:^0.1.13" - minipass: "npm:^7.0.3" - minipass-sized: "npm:^1.0.3" - minizlib: "npm:^3.0.1" - dependenciesMeta: - encoding: - optional: true - checksum: 10c0/a3147b2efe8e078c9bf9d024a0059339c5a09c5b1dded6900a219c218cc8b1b78510b62dae556b507304af226b18c3f1aeb1d48660283602d5b6586c399eed5c - languageName: node - linkType: hard - -"minipass-flush@npm:^1.0.5": - version: 1.0.5 - resolution: "minipass-flush@npm:1.0.5" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/2a51b63feb799d2bb34669205eee7c0eaf9dce01883261a5b77410c9408aa447e478efd191b4de6fc1101e796ff5892f8443ef20d9544385819093dbb32d36bd - languageName: node - linkType: hard - -"minipass-pipeline@npm:^1.2.4": - version: 1.2.4 - resolution: "minipass-pipeline@npm:1.2.4" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2 - languageName: node - linkType: hard - -"minipass-sized@npm:^1.0.3": - version: 1.0.3 - resolution: "minipass-sized@npm:1.0.3" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb - languageName: node - linkType: hard - -"minipass@npm:^3.0.0": - version: 3.3.6 - resolution: "minipass@npm:3.3.6" - dependencies: - yallist: "npm:^4.0.0" - checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c - languageName: node - linkType: hard - -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": - version: 7.1.2 - resolution: "minipass@npm:7.1.2" - checksum: 10c0/b0fd20bb9fb56e5fa9a8bfac539e8915ae07430a619e4b86ff71f5fc757ef3924b23b2c4230393af1eda647ed3d75739e4e0acb250a6b1eb277cf7f8fe449557 - languageName: node - linkType: hard - -"minizlib@npm:^3.0.1": - version: 3.0.1 - resolution: "minizlib@npm:3.0.1" - dependencies: - minipass: "npm:^7.0.4" - rimraf: "npm:^5.0.5" - checksum: 10c0/82f8bf70da8af656909a8ee299d7ed3b3372636749d29e105f97f20e88971be31f5ed7642f2e898f00283b68b701cc01307401cdc209b0efc5dd3818220e5093 - languageName: node - linkType: hard - -"mkdirp@npm:^3.0.1": - version: 3.0.1 - resolution: "mkdirp@npm:3.0.1" - bin: - mkdirp: dist/cjs/src/bin.js - checksum: 10c0/9f2b975e9246351f5e3a40dcfac99fcd0baa31fbfab615fe059fb11e51f10e4803c63de1f384c54d656e4db31d000e4767e9ef076a22e12a641357602e31d57d - languageName: node - linkType: hard - -"ms@npm:^2.1.3": - version: 2.1.3 - resolution: "ms@npm:2.1.3" - checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 - languageName: node - linkType: hard - -"negotiator@npm:^1.0.0": - version: 1.0.0 - resolution: "negotiator@npm:1.0.0" - checksum: 10c0/4c559dd52669ea48e1914f9d634227c561221dd54734070791f999c52ed0ff36e437b2e07d5c1f6e32909fc625fe46491c16e4a8f0572567d4dd15c3a4fda04b - languageName: node - linkType: hard - -"node-domexception@npm:^1.0.0": - version: 1.0.0 - resolution: "node-domexception@npm:1.0.0" - checksum: 10c0/5e5d63cda29856402df9472335af4bb13875e1927ad3be861dc5ebde38917aecbf9ae337923777af52a48c426b70148815e890a5d72760f1b4d758cc671b1a2b - languageName: node - linkType: hard - -"node-fetch@npm:2": - version: 2.7.0 - resolution: "node-fetch@npm:2.7.0" - dependencies: - whatwg-url: "npm:^5.0.0" - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - checksum: 10c0/b55786b6028208e6fbe594ccccc213cab67a72899c9234eb59dba51062a299ea853210fcf526998eaa2867b0963ad72338824450905679ff0fa304b8c5093ae8 - languageName: node - linkType: hard - -"node-fetch@npm:^3.3.2": - version: 3.3.2 - resolution: "node-fetch@npm:3.3.2" - dependencies: - data-uri-to-buffer: "npm:^4.0.0" - fetch-blob: "npm:^3.1.4" - formdata-polyfill: "npm:^4.0.10" - checksum: 10c0/f3d5e56190562221398c9f5750198b34cf6113aa304e34ee97c94fd300ec578b25b2c2906edba922050fce983338fde0d5d34fcb0fc3336ade5bd0e429ad7538 - languageName: node - linkType: hard - -"node-gyp@npm:latest": - version: 11.1.0 - resolution: "node-gyp@npm:11.1.0" - dependencies: - env-paths: "npm:^2.2.0" - exponential-backoff: "npm:^3.1.1" - glob: "npm:^10.3.10" - graceful-fs: "npm:^4.2.6" - make-fetch-happen: "npm:^14.0.3" - nopt: "npm:^8.0.0" - proc-log: "npm:^5.0.0" - semver: "npm:^7.3.5" - tar: "npm:^7.4.3" - which: "npm:^5.0.0" - bin: - node-gyp: bin/node-gyp.js - checksum: 10c0/c38977ce502f1ea41ba2b8721bd5b49bc3d5b3f813eabfac8414082faf0620ccb5211e15c4daecc23ed9f5e3e9cc4da00e575a0bcfc2a95a069294f2afa1e0cd - languageName: node - linkType: hard - -"nopt@npm:^8.0.0": - version: 8.1.0 - resolution: "nopt@npm:8.1.0" - dependencies: - abbrev: "npm:^3.0.0" - bin: - nopt: bin/nopt.js - checksum: 10c0/62e9ea70c7a3eb91d162d2c706b6606c041e4e7b547cbbb48f8b3695af457dd6479904d7ace600856bf923dd8d1ed0696f06195c8c20f02ac87c1da0e1d315ef - languageName: node - linkType: hard - -"object-inspect@npm:^1.13.3": - version: 1.13.4 - resolution: "object-inspect@npm:1.13.4" - checksum: 10c0/d7f8711e803b96ea3191c745d6f8056ce1f2496e530e6a19a0e92d89b0fa3c76d910c31f0aa270432db6bd3b2f85500a376a83aaba849a8d518c8845b3211692 - languageName: node - linkType: hard - -"p-map@npm:^7.0.2": - version: 7.0.3 - resolution: "p-map@npm:7.0.3" - checksum: 10c0/46091610da2b38ce47bcd1d8b4835a6fa4e832848a6682cf1652bc93915770f4617afc844c10a77d1b3e56d2472bb2d5622353fa3ead01a7f42b04fc8e744a5c - languageName: node - linkType: hard - -"package-json-from-dist@npm:^1.0.0": - version: 1.0.1 - resolution: "package-json-from-dist@npm:1.0.1" - checksum: 10c0/62ba2785eb655fec084a257af34dbe24292ab74516d6aecef97ef72d4897310bc6898f6c85b5cd22770eaa1ce60d55a0230e150fb6a966e3ecd6c511e23d164b - languageName: node - linkType: hard - -"path-key@npm:^3.1.0": - version: 3.1.1 - resolution: "path-key@npm:3.1.1" - checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c - languageName: node - linkType: hard - -"path-scurry@npm:^1.11.1": - version: 1.11.1 - resolution: "path-scurry@npm:1.11.1" - dependencies: - lru-cache: "npm:^10.2.0" - minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - checksum: 10c0/32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d - languageName: node - linkType: hard - -"proc-log@npm:^5.0.0": - version: 5.0.0 - resolution: "proc-log@npm:5.0.0" - checksum: 10c0/bbe5edb944b0ad63387a1d5b1911ae93e05ce8d0f60de1035b218cdcceedfe39dbd2c697853355b70f1a090f8f58fe90da487c85216bf9671f9499d1a897e9e3 - languageName: node - linkType: hard - -"process@npm:^0.11.10": - version: 0.11.10 - resolution: "process@npm:0.11.10" - checksum: 10c0/40c3ce4b7e6d4b8c3355479df77aeed46f81b279818ccdc500124e6a5ab882c0cc81ff7ea16384873a95a74c4570b01b120f287abbdd4c877931460eca6084b3 - languageName: node - linkType: hard - -"promise-retry@npm:^2.0.1": - version: 2.0.1 - resolution: "promise-retry@npm:2.0.1" - dependencies: - err-code: "npm:^2.0.2" - retry: "npm:^0.12.0" - checksum: 10c0/9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96 - languageName: node - linkType: hard - -"qs@npm:^6.11.2": - version: 6.14.0 - resolution: "qs@npm:6.14.0" - dependencies: - side-channel: "npm:^1.1.0" - checksum: 10c0/8ea5d91bf34f440598ee389d4a7d95820e3b837d3fd9f433871f7924801becaa0cd3b3b4628d49a7784d06a8aea9bc4554d2b6d8d584e2d221dc06238a42909c - languageName: node - linkType: hard - -"readable-stream@npm:^4.5.2": - version: 4.7.0 - resolution: "readable-stream@npm:4.7.0" - dependencies: - abort-controller: "npm:^3.0.0" - buffer: "npm:^6.0.3" - events: "npm:^3.3.0" - process: "npm:^0.11.10" - string_decoder: "npm:^1.3.0" - checksum: 10c0/fd86d068da21cfdb10f7a4479f2e47d9c0a9b0c862fc0c840a7e5360201580a55ac399c764b12a4f6fa291f8cee74d9c4b7562e0d53b3c4b2769f2c98155d957 - languageName: node - linkType: hard - -"resolve-pkg-maps@npm:^1.0.0": - version: 1.0.0 - resolution: "resolve-pkg-maps@npm:1.0.0" - checksum: 10c0/fb8f7bbe2ca281a73b7ef423a1cbc786fb244bd7a95cbe5c3fba25b27d327150beca8ba02f622baea65919a57e061eb5005204daa5f93ed590d9b77463a567ab - languageName: node - linkType: hard - -"retry@npm:^0.12.0": - version: 0.12.0 - resolution: "retry@npm:0.12.0" - checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe - languageName: node - linkType: hard - -"rimraf@npm:^5.0.5": - version: 5.0.10 - resolution: "rimraf@npm:5.0.10" - dependencies: - glob: "npm:^10.3.7" - bin: - rimraf: dist/esm/bin.mjs - checksum: 10c0/7da4fd0e15118ee05b918359462cfa1e7fe4b1228c7765195a45b55576e8c15b95db513b8466ec89129666f4af45ad978a3057a02139afba1a63512a2d9644cc - languageName: node - linkType: hard - -"safe-buffer@npm:~5.1.1": - version: 5.1.2 - resolution: "safe-buffer@npm:5.1.2" - checksum: 10c0/780ba6b5d99cc9a40f7b951d47152297d0e260f0df01472a1b99d4889679a4b94a13d644f7dbc4f022572f09ae9005fa2fbb93bbbd83643316f365a3e9a45b21 - languageName: node - linkType: hard - -"safe-buffer@npm:~5.2.0": - version: 5.2.1 - resolution: "safe-buffer@npm:5.2.1" - checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 - languageName: node - linkType: hard - -"safer-buffer@npm:>= 2.1.2 < 3.0.0": - version: 2.1.2 - resolution: "safer-buffer@npm:2.1.2" - checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 - languageName: node - linkType: hard - -"semver@npm:^7.3.5": - version: 7.7.1 - resolution: "semver@npm:7.7.1" - bin: - semver: bin/semver.js - checksum: 10c0/fd603a6fb9c399c6054015433051bdbe7b99a940a8fb44b85c2b524c4004b023d7928d47cb22154f8d054ea7ee8597f586605e05b52047f048278e4ac56ae958 - languageName: node - linkType: hard - -"shebang-command@npm:^2.0.0": - version: 2.0.0 - resolution: "shebang-command@npm:2.0.0" - dependencies: - shebang-regex: "npm:^3.0.0" - checksum: 10c0/a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e - languageName: node - linkType: hard - -"shebang-regex@npm:^3.0.0": - version: 3.0.0 - resolution: "shebang-regex@npm:3.0.0" - checksum: 10c0/1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 - languageName: node - linkType: hard - -"side-channel-list@npm:^1.0.0": - version: 1.0.0 - resolution: "side-channel-list@npm:1.0.0" - dependencies: - es-errors: "npm:^1.3.0" - object-inspect: "npm:^1.13.3" - checksum: 10c0/644f4ac893456c9490ff388bf78aea9d333d5e5bfc64cfb84be8f04bf31ddc111a8d4b83b85d7e7e8a7b845bc185a9ad02c052d20e086983cf59f0be517d9b3d - languageName: node - linkType: hard - -"side-channel-map@npm:^1.0.1": - version: 1.0.1 - resolution: "side-channel-map@npm:1.0.1" - dependencies: - call-bound: "npm:^1.0.2" - es-errors: "npm:^1.3.0" - get-intrinsic: "npm:^1.2.5" - object-inspect: "npm:^1.13.3" - checksum: 10c0/010584e6444dd8a20b85bc926d934424bd809e1a3af941cace229f7fdcb751aada0fb7164f60c2e22292b7fa3c0ff0bce237081fd4cdbc80de1dc68e95430672 - languageName: node - linkType: hard - -"side-channel-weakmap@npm:^1.0.2": - version: 1.0.2 - resolution: "side-channel-weakmap@npm:1.0.2" - dependencies: - call-bound: "npm:^1.0.2" - es-errors: "npm:^1.3.0" - get-intrinsic: "npm:^1.2.5" - object-inspect: "npm:^1.13.3" - side-channel-map: "npm:^1.0.1" - checksum: 10c0/71362709ac233e08807ccd980101c3e2d7efe849edc51455030327b059f6c4d292c237f94dc0685031dd11c07dd17a68afde235d6cf2102d949567f98ab58185 - languageName: node - linkType: hard - -"side-channel@npm:^1.1.0": - version: 1.1.0 - resolution: "side-channel@npm:1.1.0" - dependencies: - es-errors: "npm:^1.3.0" - object-inspect: "npm:^1.13.3" - side-channel-list: "npm:^1.0.0" - side-channel-map: "npm:^1.0.1" - side-channel-weakmap: "npm:^1.0.2" - checksum: 10c0/cb20dad41eb032e6c24c0982e1e5a24963a28aa6122b4f05b3f3d6bf8ae7fd5474ef382c8f54a6a3ab86e0cac4d41a23bd64ede3970e5bfb50326ba02a7996e6 - languageName: node - linkType: hard - -"signal-exit@npm:^4.0.1": - version: 4.1.0 - resolution: "signal-exit@npm:4.1.0" - checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 - languageName: node - linkType: hard - -"smart-buffer@npm:^4.2.0": - version: 4.2.0 - resolution: "smart-buffer@npm:4.2.0" - checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539 - languageName: node - linkType: hard - -"socks-proxy-agent@npm:^8.0.3": - version: 8.0.5 - resolution: "socks-proxy-agent@npm:8.0.5" - dependencies: - agent-base: "npm:^7.1.2" - debug: "npm:^4.3.4" - socks: "npm:^2.8.3" - checksum: 10c0/5d2c6cecba6821389aabf18728325730504bf9bb1d9e342e7987a5d13badd7a98838cc9a55b8ed3cb866ad37cc23e1086f09c4d72d93105ce9dfe76330e9d2a6 - languageName: node - linkType: hard - -"socks@npm:^2.8.3": - version: 2.8.4 - resolution: "socks@npm:2.8.4" - dependencies: - ip-address: "npm:^9.0.5" - smart-buffer: "npm:^4.2.0" - checksum: 10c0/00c3271e233ccf1fb83a3dd2060b94cc37817e0f797a93c560b9a7a86c4a0ec2961fb31263bdd24a3c28945e24868b5f063cd98744171d9e942c513454b50ae5 - languageName: node - linkType: hard - -"sprintf-js@npm:^1.1.3": - version: 1.1.3 - resolution: "sprintf-js@npm:1.1.3" - checksum: 10c0/09270dc4f30d479e666aee820eacd9e464215cdff53848b443964202bf4051490538e5dd1b42e1a65cf7296916ca17640aebf63dae9812749c7542ee5f288dec - languageName: node - linkType: hard - -"ssri@npm:^12.0.0": - version: 12.0.0 - resolution: "ssri@npm:12.0.0" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/caddd5f544b2006e88fa6b0124d8d7b28208b83c72d7672d5ade44d794525d23b540f3396108c4eb9280dcb7c01f0bef50682f5b4b2c34291f7c5e211fd1417d - languageName: node - linkType: hard - -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0": - version: 4.2.3 - resolution: "string-width@npm:4.2.3" - dependencies: - emoji-regex: "npm:^8.0.0" - is-fullwidth-code-point: "npm:^3.0.0" - strip-ansi: "npm:^6.0.1" - checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b - languageName: node - linkType: hard - -"string-width@npm:^5.0.1, string-width@npm:^5.1.2": - version: 5.1.2 - resolution: "string-width@npm:5.1.2" - dependencies: - eastasianwidth: "npm:^0.2.0" - emoji-regex: "npm:^9.2.2" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca - languageName: node - linkType: hard - -"string_decoder@npm:^1.3.0": - version: 1.3.0 - resolution: "string_decoder@npm:1.3.0" - dependencies: - safe-buffer: "npm:~5.2.0" - checksum: 10c0/810614ddb030e271cd591935dcd5956b2410dd079d64ff92a1844d6b7588bf992b3e1b69b0f4d34a3e06e0bd73046ac646b5264c1987b20d0601f81ef35d731d - languageName: node - linkType: hard - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": - version: 6.0.1 - resolution: "strip-ansi@npm:6.0.1" - dependencies: - ansi-regex: "npm:^5.0.1" - checksum: 10c0/1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952 - languageName: node - linkType: hard - -"strip-ansi@npm:^7.0.1": - version: 7.1.0 - resolution: "strip-ansi@npm:7.1.0" - dependencies: - ansi-regex: "npm:^6.0.1" - checksum: 10c0/a198c3762e8832505328cbf9e8c8381de14a4fa50a4f9b2160138158ea88c0f5549fb50cb13c651c3088f47e63a108b34622ec18c0499b6c8c3a5ddf6b305ac4 - languageName: node - linkType: hard - -"system-test-container@workspace:.": - version: 0.0.0-use.local - resolution: "system-test-container@workspace:." - dependencies: - "@hono/node-server": "npm:^1.13.8" - "@hono/node-ws": "npm:^1.1.0" - "@rivet-gg/actor-core": "npm:^5.1.2" - "@rivet-gg/api": "npm:^24.6.2" - "@types/deno": "npm:^2.2.0" - "@types/node": "npm:^22.13.9" - "@types/ws": "npm:^8.18.0" - dgram: "npm:^1.0.1" - hono: "npm:^4.6.17" - node-fetch: "npm:^3.3.2" - tsx: "npm:^4.7.0" - typescript: "npm:^5.3.3" - ws: "npm:^8.18.1" - languageName: unknown - linkType: soft - -"tar@npm:^7.4.3": - version: 7.4.3 - resolution: "tar@npm:7.4.3" - dependencies: - "@isaacs/fs-minipass": "npm:^4.0.0" - chownr: "npm:^3.0.0" - minipass: "npm:^7.1.2" - minizlib: "npm:^3.0.1" - mkdirp: "npm:^3.0.1" - yallist: "npm:^5.0.0" - checksum: 10c0/d4679609bb2a9b48eeaf84632b6d844128d2412b95b6de07d53d8ee8baf4ca0857c9331dfa510390a0727b550fd543d4d1a10995ad86cdf078423fbb8d99831d - languageName: node - linkType: hard - -"tr46@npm:~0.0.3": - version: 0.0.3 - resolution: "tr46@npm:0.0.3" - checksum: 10c0/047cb209a6b60c742f05c9d3ace8fa510bff609995c129a37ace03476a9b12db4dbf975e74600830ef0796e18882b2381fb5fb1f6b4f96b832c374de3ab91a11 - languageName: node - linkType: hard - -"tsx@npm:^4.7.0": - version: 4.19.3 - resolution: "tsx@npm:4.19.3" - dependencies: - esbuild: "npm:~0.25.0" - fsevents: "npm:~2.3.3" - get-tsconfig: "npm:^4.7.5" - dependenciesMeta: - fsevents: - optional: true - bin: - tsx: dist/cli.mjs - checksum: 10c0/cacfb4cf1392ae10e8e4fe032ad26ccb07cd8a3b32e5a0da270d9c48d06ee74f743e4a84686cbc9d89b48032d59bbc56cd911e076f53cebe61dc24fa525ff790 - languageName: node - linkType: hard - -"typescript@npm:^5.3.3": - version: 5.8.2 - resolution: "typescript@npm:5.8.2" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10c0/5c4f6fbf1c6389b6928fe7b8fcd5dc73bb2d58cd4e3883f1d774ed5bd83b151cbac6b7ecf11723de56d4676daeba8713894b1e9af56174f2f9780ae7848ec3c6 - languageName: node - linkType: hard - -"typescript@patch:typescript@npm%3A^5.3.3#optional!builtin": - version: 5.8.2 - resolution: "typescript@patch:typescript@npm%3A5.8.2#optional!builtin::version=5.8.2&hash=5786d5" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10c0/5448a08e595cc558ab321e49d4cac64fb43d1fa106584f6ff9a8d8e592111b373a995a1d5c7f3046211c8a37201eb6d0f1566f15cdb7a62a5e3be01d087848e2 - languageName: node - linkType: hard - -"undici-types@npm:~6.20.0": - version: 6.20.0 - resolution: "undici-types@npm:6.20.0" - checksum: 10c0/68e659a98898d6a836a9a59e6adf14a5d799707f5ea629433e025ac90d239f75e408e2e5ff086afc3cace26f8b26ee52155293564593fbb4a2f666af57fc59bf - languageName: node - linkType: hard - -"unique-filename@npm:^4.0.0": - version: 4.0.0 - resolution: "unique-filename@npm:4.0.0" - dependencies: - unique-slug: "npm:^5.0.0" - checksum: 10c0/38ae681cceb1408ea0587b6b01e29b00eee3c84baee1e41fd5c16b9ed443b80fba90c40e0ba69627e30855570a34ba8b06702d4a35035d4b5e198bf5a64c9ddc - languageName: node - linkType: hard - -"unique-slug@npm:^5.0.0": - version: 5.0.0 - resolution: "unique-slug@npm:5.0.0" - dependencies: - imurmurhash: "npm:^0.1.4" - checksum: 10c0/d324c5a44887bd7e105ce800fcf7533d43f29c48757ac410afd42975de82cc38ea2035c0483f4de82d186691bf3208ef35c644f73aa2b1b20b8e651be5afd293 - languageName: node - linkType: hard - -"url-join@npm:^5.0.0": - version: 5.0.0 - resolution: "url-join@npm:5.0.0" - checksum: 10c0/ed2b166b4b5a98adcf6828a48b6bd6df1dac4c8a464a73cf4d8e2457ed410dd8da6be0d24855b86026cd7f5c5a3657c1b7b2c7a7c5b8870af17635a41387b04c - languageName: node - linkType: hard - -"web-streams-polyfill@npm:^3.0.3": - version: 3.3.3 - resolution: "web-streams-polyfill@npm:3.3.3" - checksum: 10c0/64e855c47f6c8330b5436147db1c75cb7e7474d924166800e8e2aab5eb6c76aac4981a84261dd2982b3e754490900b99791c80ae1407a9fa0dcff74f82ea3a7f - languageName: node - linkType: hard - -"webidl-conversions@npm:^3.0.0": - version: 3.0.1 - resolution: "webidl-conversions@npm:3.0.1" - checksum: 10c0/5612d5f3e54760a797052eb4927f0ddc01383550f542ccd33d5238cfd65aeed392a45ad38364970d0a0f4fea32e1f4d231b3d8dac4a3bdd385e5cf802ae097db - languageName: node - linkType: hard - -"whatwg-url@npm:^5.0.0": - version: 5.0.0 - resolution: "whatwg-url@npm:5.0.0" - dependencies: - tr46: "npm:~0.0.3" - webidl-conversions: "npm:^3.0.0" - checksum: 10c0/1588bed84d10b72d5eec1d0faa0722ba1962f1821e7539c535558fb5398d223b0c50d8acab950b8c488b4ba69043fd833cc2697056b167d8ad46fac3995a55d5 - languageName: node - linkType: hard - -"which@npm:^2.0.1": - version: 2.0.2 - resolution: "which@npm:2.0.2" - dependencies: - isexe: "npm:^2.0.0" - bin: - node-which: ./bin/node-which - checksum: 10c0/66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f - languageName: node - linkType: hard - -"which@npm:^5.0.0": - version: 5.0.0 - resolution: "which@npm:5.0.0" - dependencies: - isexe: "npm:^3.1.1" - bin: - node-which: bin/which.js - checksum: 10c0/e556e4cd8b7dbf5df52408c9a9dd5ac6518c8c5267c8953f5b0564073c66ed5bf9503b14d876d0e9c7844d4db9725fb0dcf45d6e911e17e26ab363dc3965ae7b - languageName: node - linkType: hard - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version: 7.0.0 - resolution: "wrap-ansi@npm:7.0.0" - dependencies: - ansi-styles: "npm:^4.0.0" - string-width: "npm:^4.1.0" - strip-ansi: "npm:^6.0.0" - checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da - languageName: node - linkType: hard - -"wrap-ansi@npm:^8.1.0": - version: 8.1.0 - resolution: "wrap-ansi@npm:8.1.0" - dependencies: - ansi-styles: "npm:^6.1.0" - string-width: "npm:^5.0.1" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 - languageName: node - linkType: hard - -"ws@npm:^8.17.0, ws@npm:^8.18.1": - version: 8.18.1 - resolution: "ws@npm:8.18.1" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 10c0/e498965d6938c63058c4310ffb6967f07d4fa06789d3364829028af380d299fe05762961742971c764973dce3d1f6a2633fe8b2d9410c9b52e534b4b882a99fa - languageName: node - linkType: hard - -"yallist@npm:^4.0.0": - version: 4.0.0 - resolution: "yallist@npm:4.0.0" - checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a - languageName: node - linkType: hard - -"yallist@npm:^5.0.0": - version: 5.0.0 - resolution: "yallist@npm:5.0.0" - checksum: 10c0/a499c81ce6d4a1d260d4ea0f6d49ab4da09681e32c3f0472dee16667ed69d01dae63a3b81745a24bd78476ec4fcf856114cb4896ace738e01da34b2c42235416 - languageName: node - linkType: hard - -"zod@npm:^3.24.1": - version: 3.24.2 - resolution: "zod@npm:3.24.2" - checksum: 10c0/c638c7220150847f13ad90635b3e7d0321b36cce36f3fc6050ed960689594c949c326dfe2c6fa87c14b126ee5d370ccdebd6efb304f41ef5557a4aaca2824565 - languageName: node - linkType: hard diff --git a/examples/system-test-route/Dockerfile b/examples/system-test-route/Dockerfile deleted file mode 100644 index 90e753ad64..0000000000 --- a/examples/system-test-route/Dockerfile +++ /dev/null @@ -1,26 +0,0 @@ -# Build stage -FROM node:22 as builder -WORKDIR /app -COPY package.json yarn.lock ./ -RUN yarn install -COPY . . -RUN yarn build - -# Production stage -FROM node:22-slim -WORKDIR /app - -# Create rivet user and set proper permissions -RUN groupadd -r rivet && useradd -r -g rivet rivet -COPY package.json yarn.lock ./ -RUN yarn install --production && \ - chown -R rivet:rivet /app - -COPY --from=builder /app/dist ./dist -RUN chown -R rivet:rivet /app/dist - -# Switch to non-root user -USER rivet - -# Start the server -CMD ["node", "dist/src/index.js"] diff --git a/examples/system-test-route/README.md b/examples/system-test-route/README.md deleted file mode 100644 index 1ed71a6e58..0000000000 --- a/examples/system-test-route/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# System Test - -Actors for simple tests of E2E system functionality. - -## Prerequisites - -- [Rivet CLI](https://rivet.gg/docs/setup) - -## Deploying - -```sh -rivet deploy -``` - -## Testing - -Build the API: - -```sh -cd sdks/api/full/typescript -yarn build -``` - -Run the test: - -```sh -BUILD=http-isolate rivet shell -e "yarn test" -# or -BUILD=http-container rivet shell -e "yarn test" -``` - diff --git a/examples/system-test-route/package.json b/examples/system-test-route/package.json deleted file mode 100644 index b5f8edb322..0000000000 --- a/examples/system-test-route/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "system-test-route", - "version": "1.0.0", - "private": true, - "type": "module", - "dependencies": { - "@hono/node-server": "^1.13.8", - "@hono/node-ws": "^1.1.0", - "hono": "^4.6.17" - }, - "devDependencies": { - "@rivet-gg/actor-core": "^5.1.2", - "@types/deno": "^2.2.0", - "@types/node": "^22.13.9", - "@types/ws": "^8.18.0", - "node-fetch": "^3.3.2", - "tsx": "^4.7.0", - "typescript": "^5.3.3", - "ws": "^8.18.1" - }, - "scripts": { - "test-isolate": "BUILD=http-isolate tsx tests/client.ts", - "test-container": "BUILD=http-container tsx tests/client.ts", - "test": "npm run test-isolate", - "build": "tsc --outDir dist" - } -} diff --git a/examples/system-test-route/rivet.jsonc b/examples/system-test-route/rivet.jsonc deleted file mode 100644 index 442952e272..0000000000 --- a/examples/system-test-route/rivet.jsonc +++ /dev/null @@ -1,8 +0,0 @@ -{ - "functions": { - "http": { - "dockerfile": "Dockerfile", - "path": "/container" - } - } -} diff --git a/examples/system-test-route/src/index.ts b/examples/system-test-route/src/index.ts deleted file mode 100644 index f2dd821ae4..0000000000 --- a/examples/system-test-route/src/index.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { serve } from "@hono/node-server"; -import { Hono } from "hono"; - -// Setup auto-exit timer -setTimeout(() => { - console.error( - "Actor should've been destroyed by now. Automatically exiting.", - ); - - if (typeof Deno !== "undefined") Deno.exit(1); - else process.exit(1); -}, 60 * 1000); - -let tickIndex = 0; -setInterval(() => { - tickIndex++; - console.log("Tick", tickIndex); - console.log(JSON.stringify({ level: "info", message: "tick", tickIndex })); - console.log(`level=info message=tick tickIndex=${tickIndex}`); -}, 1000); - -// Get port from environment -const portEnv = - typeof Deno !== "undefined" - ? Deno.env.get("PORT_HTTP") - : process.env.PORT_HTTP; -if (!portEnv) { - throw new Error("missing PORT_HTTP"); -} -const port = Number.parseInt(portEnv); - -// Create app with health endpoint -const app = new Hono(); - -app.get("/health", (c) => c.text("ok")); - -// Add a catch-all route to handle any other path (for testing routeSubpaths) -app.all("*", (c) => { - console.log( - `Received request to ${c.req.url} from ${c.req.header("x-forwarded-for") || "unknown"}`, - ); - return c.json({ - path: c.req.path, - query: c.req.query(), - }); -}); - -console.log(`Listening on port ${port}`); - -serve({ fetch: app.fetch, port }); diff --git a/examples/system-test-route/tests/client.ts b/examples/system-test-route/tests/client.ts deleted file mode 100644 index be5ce46a1b..0000000000 --- a/examples/system-test-route/tests/client.ts +++ /dev/null @@ -1,1709 +0,0 @@ -//import { RivetClient } from "@rivet-gg/api-full"; -//import crypto from "crypto"; -//import http from "http"; -// -//// Can be opt since they're not required for dev -//const RIVET_ENDPOINT = process.env.RIVET_ENDPOINT; -//const RIVET_SERVICE_TOKEN = process.env.RIVET_SERVICE_TOKEN; -//const RIVET_PROJECT = process.env.RIVET_PROJECT; -//const RIVET_ENVIRONMENT = process.env.RIVET_ENVIRONMENT; -// -//// Determine test kind from environment variable -//const BUILD_NAME = process.env.BUILD; -//if (BUILD_NAME !== "http-isolate" && BUILD_NAME !== "http-container") { -// throw new Error( -// "Must specify BUILD environment variable as either 'http-isolate' or 'http-container'", -// ); -//} -// -//let region = process.env.REGION; -//if (!region || region.length === 0) { -// region = undefined; -//} -// -//const client = new RivetClient({ -// environment: RIVET_ENDPOINT, -// token: RIVET_SERVICE_TOKEN, -//}); -// -//// Interface definitions -//interface RouteConfig { -// path: string; -// routeSubpaths: boolean; -// stripPrefix?: boolean; // Whether to strip the prefix from the path in request handlers -// selectorIndex?: number; // Index of the selector to use from selectors array -//} -// -//interface TestContext { -// actorIds: string[]; -// routeIds: string[]; -// selectors: string[]; // Array of selectors -// hostname: string; -// actorsBySelector: Record; // Maps selectors to their actor IDs -// routes?: RouteConfig[]; // Store the routes for this test -//} -// -//interface TestConfig { -// name: string; -// numActors?: number; -// numSelectors?: number; // Number of different selectors to create -// routes?: RouteConfig[]; // Each route can specify which selector to use -//} -// -//// Helper function to make HTTP requests with a custom host header -//async function makeRequest(url: string, hostname: string): Promise { -// return new Promise((resolve, reject) => { -// const parsedUrl = new URL(url); -// -// const options = { -// hostname: parsedUrl.hostname, -// port: parsedUrl.port || 80, -// path: parsedUrl.pathname + parsedUrl.search, -// method: "GET", -// headers: { -// Accept: "application/json", -// Host: hostname, -// }, -// }; -// -// const req = http.request(options, (res: any) => { -// if (res.statusCode !== 200) { -// console.error( -// `Request failed: ${res.statusCode} ${res.statusMessage}`, -// ); -// // Don't reject, just continue the loop -// resolve(null); -// return; -// } -// -// let rawData = ""; -// res.on("data", (chunk: any) => { -// rawData += chunk; -// }); -// res.on("end", () => { -// try { -// const parsedData = JSON.parse(rawData); -// resolve(parsedData); -// } catch (e) { -// console.error("Error parsing response:", e); -// reject(e); -// } -// }); -// }); -// -// req.on("error", (e: any) => { -// console.error(`Request error: ${e.message}`); -// reject(e); -// }); -// -// req.end(); -// }); -//} -// -//// Helper function to create actors with a specific selector -//async function createActors( -// selectorTag: string, -// numberOfActors: number = 2, -//): Promise { -// const createdActorIds: string[] = []; -// -// for (let i = 1; i <= numberOfActors; i++) { -// console.time(`create actor ${i}`); -// console.log(`Creating actor ${i} with tag`, { -// selector: selectorTag, -// }); -// -// const { actor } = await client.actors.create({ -// project: RIVET_PROJECT, -// environment: RIVET_ENVIRONMENT, -// body: { -// region, -// tags: { -// selector: selectorTag, -// instance: i.toString(), -// }, -// buildTags: { name: BUILD_NAME, current: "true" }, -// network: { -// ports: { -// http: { -// protocol: "https", -// routing: { -// guard: {}, -// }, -// }, -// }, -// }, -// lifecycle: { -// durable: false, -// }, -// ...(BUILD_NAME === "http-container" -// ? { -// resources: { -// cpu: 100, -// memory: 100, -// }, -// } -// : {}), -// }, -// }); -// -// createdActorIds.push(actor.id); -// console.timeEnd(`create actor ${i}`); -// console.log(`Created actor ${i} with ID:`, actor.id); -// } -// -// // Wait for actors to be ready -// await new Promise((resolve) => setTimeout(resolve, 2000)); -// return createdActorIds; -//} -// -//// Helper function to create a route -//async function createRoute( -// routeId: string, -// hostname: string, -// selectorTag: string, -// path: string, -// routeSubpaths: boolean = false, -// stripPrefix: boolean = true, -//): Promise { -// console.time(`create route ${routeId}`); -// console.log(`Creating route ${routeId} with selector tag`, { -// selector: selectorTag, -// path, -// routeSubpaths, -// stripPrefix, -// }); -// -// await client.routes.update(routeId, { -// project: RIVET_PROJECT, -// environment: RIVET_ENVIRONMENT, -// body: { -// hostname, -// path, -// routeSubpaths, -// stripPrefix, -// target: { -// actors: { -// selectorTags: { -// selector: selectorTag, -// }, -// }, -// }, -// }, -// }); -// -// console.timeEnd(`create route ${routeId}`); -// console.log(`Created route ${routeId}.`); -// -// // Wait for route to be active -// await new Promise((resolve) => setTimeout(resolve, 2000)); -//} -// -//// Helper function to calculate expected path based on route configuration -//function getExpectedPath( -// requestPath: string, -// routePath: string, -// stripPrefix: boolean, -//): string { -// // Extract the query string if present -// const queryStringIndex = requestPath.indexOf("?"); -// const pathWithoutQuery = -// queryStringIndex >= 0 -// ? requestPath.substring(0, queryStringIndex) -// : requestPath; -// -// // If stripPrefix is false, the full path should be returned -// if (!stripPrefix) { -// return pathWithoutQuery; -// } -// -// // If stripPrefix is true, we need to strip the route path prefix -// if (routePath === "") { -// // For empty path routes, return the path as is -// return pathWithoutQuery; -// } -// -// // For non-empty paths with stripPrefix=true -// if (pathWithoutQuery === routePath) { -// // If exact match, return "/" -// return "/"; -// } else if (pathWithoutQuery.startsWith(routePath + "/")) { -// // If it's a subpath, remove the prefix -// return pathWithoutQuery.substring(routePath.length); -// } -// -// // Default case - shouldn't happen with proper routing -// return pathWithoutQuery; -//} -// -//// Helper function to test a route -//async function testRoute( -// hostname: string, -// path: string, -// numActorsExpected: number = 2, -// maxRequests: number = 20, -// route?: RouteConfig, // Added route config parameter -//): Promise> { -// const actorIds = new Set(); -// let successfulMatches = 0; -// let totalRequests = 0; -// let pathValidationFailed = false; -// -// // Using localhost with Host header for local testing -// const testUrl = `http://localhost:7080${path}`; -// console.log(`Testing route at: ${testUrl} (with Host: ${hostname})`); -// console.time(`route-test-${path}`); -// -// // Calculate expected path if route is provided -// let expectedPath = route -// ? getExpectedPath( -// path, -// route.path, -// route.stripPrefix !== undefined ? route.stripPrefix : true, -// ) -// : path; -// -// // URL-encoded characters like %20 will be decoded by the server -// // Decode the expected path to match server behavior -// expectedPath = decodeURIComponent(expectedPath); -// -// if (route) { -// console.log( -// `Route config: path=${route.path}, routeSubpaths=${route.routeSubpaths}, stripPrefix=${route.stripPrefix}`, -// ); -// console.log(`Expected path in response: ${expectedPath}`); -// } -// -// while (actorIds.size < numActorsExpected && totalRequests < maxRequests) { -// totalRequests++; -// -// try { -// const data = await makeRequest(testUrl, hostname); -// -// // If request failed or returned null, continue to next iteration -// if (!data) { -// continue; -// } -// -// console.log( -// `Request ${totalRequests}: Response from actor ${data.actorId} with path ${data.path}`, -// ); -// -// // Validate the path in the response matches the expected path -// if (data.path !== expectedPath) { -// console.error( -// `❌ Path validation failed: Expected ${expectedPath}, got ${data.path}`, -// ); -// pathValidationFailed = true; -// } else { -// console.log(`✅ Path validation passed: ${data.path}`); -// } -// -// // Log query parameters if present -// if (data.query && Object.keys(data.query).length > 0) { -// console.log(`Query parameters received:`, data.query); -// } -// -// // Track the actor IDs we've seen -// if (data.actorId) { -// actorIds.add(data.actorId); -// successfulMatches++; -// } -// -// // If we've found all expected actors, we're done -// if (actorIds.size === numActorsExpected) { -// console.log( -// `Successfully received responses from all ${numActorsExpected} actors!`, -// ); -// break; -// } -// -// // Small delay between requests -// await new Promise((resolve) => setTimeout(resolve, 200)); -// } catch (error) { -// console.error("Error making request:", error); -// // Wait a bit longer if there's an error -// await new Promise((resolve) => setTimeout(resolve, 500)); -// } -// } -// -// console.timeEnd(`route-test-${path}`); -// console.log( -// `Test completed. Matched ${actorIds.size}/${numActorsExpected} actors in ${totalRequests} requests.`, -// ); -// console.log(`Actors matched: ${Array.from(actorIds).join(", ")}`); -// -// if (actorIds.size < numActorsExpected) { -// console.error( -// `Failed to reach all ${numActorsExpected} actors through the route!`, -// ); -// } -// -// if (pathValidationFailed) { -// console.error( -// "Path validation failed: The path in the response did not match the expected path", -// ); -// throw new Error(`Path validation failed for ${path}`); -// } -// -// // Final stats -// console.log(` -//Route Test Results for ${path}: -//------------------ -//Total requests: ${totalRequests} -//Successful responses: ${successfulMatches} -//Unique actors reached: ${actorIds.size}/${numActorsExpected} -//Route: ${testUrl} (Host: ${hostname}) -//Path validation: ${pathValidationFailed ? "❌ Failed" : "✅ Passed"} -//------------------ -// `); -// -// return actorIds; -//} -// -//// Helper function to verify routes exist -//async function verifyRouteExists(hostname: string): Promise { -// console.time("list routes"); -// console.log("Listing routes to verify our route exists"); -// const { routes } = await client.routes.list({ -// project: RIVET_PROJECT, -// environment: RIVET_ENVIRONMENT, -// }); -// console.timeEnd("list routes"); -// -// // Find our route in the list -// const ourRoute = routes.find((route) => route.hostname === hostname); -// if (!ourRoute) { -// console.error( -// `Route with hostname ${hostname} not found in routes list!`, -// ); -// return false; -// } -// console.log("✅ Found our route in the list:", ourRoute); -// return true; -//} -// -//// Helper function to delete resources -//async function cleanup(context: TestContext): Promise { -// // Cleanup: delete routes first -// for (const routeId of context.routeIds) { -// console.log("Deleting route", routeId); -// try { -// await client.routes.delete(routeId, { -// project: RIVET_PROJECT, -// environment: RIVET_ENVIRONMENT, -// }); -// console.log(`Route ${routeId} deleted successfully`); -// } catch (err) { -// console.error(`Error deleting route ${routeId}:`, err); -// } -// } -// -// // Then delete all actors -// for (let i = 0; i < context.actorIds.length; i++) { -// const actorId = context.actorIds[i]; -// console.log(`Destroying actor ${i + 1}:`, actorId); -// try { -// await client.actors.destroy(actorId, { -// project: RIVET_PROJECT, -// environment: RIVET_ENVIRONMENT, -// }); -// } catch (err) { -// console.error(`Error destroying actor ${i + 1}:`, err); -// } -// } -//} -// -//// Core test setup function that handles resource creation and cleanup -//async function setupTest( -// config: TestConfig, -// testFn: (context: TestContext) => Promise, -//): Promise { -// console.log(`\n=== ${config.name} ===\n`); -// -// const baseSelector = `test-${crypto.randomBytes(4).toString("hex")}`; -// const hostname = `route-${crypto.randomBytes(4).toString("hex")}.rivet-job.local`; -// -// const context: TestContext = { -// actorIds: [], -// routeIds: [], -// selectors: [], -// hostname, -// actorsBySelector: {}, -// routes: config.routes, -// }; -// -// try { -// // Create selectors based on config -// const numSelectors = config.numSelectors || 1; -// -// // Create selectors and actors for each selector -// for (let i = 0; i < numSelectors; i++) { -// const selectorName = -// numSelectors === 1 ? baseSelector : `${baseSelector}-${i + 1}`; -// context.selectors.push(selectorName); -// -// console.log( -// `Creating actors with selector ${selectorName} (${i + 1}/${numSelectors})`, -// ); -// const actors = await createActors( -// selectorName, -// config.numActors || 2, -// ); -// context.actorIds.push(...actors); -// context.actorsBySelector[selectorName] = actors; -// } -// -// // Create routes from config -// if (config.routes && config.routes.length > 0) { -// for (let i = 0; i < config.routes.length; i++) { -// const route = config.routes[i]; -// const routeId = `route-${crypto.randomBytes(4).toString("hex")}${i > 0 ? `-${i}` : ""}`; -// -// // Determine which selector to use for this route -// const selectorIndex = -// route.selectorIndex !== undefined ? route.selectorIndex : 0; -// if (selectorIndex >= context.selectors.length) { -// throw new Error( -// `Route ${i} references selector ${selectorIndex} but only ${context.selectors.length} selectors were created`, -// ); -// } -// -// const selector = context.selectors[selectorIndex]; -// -// console.log( -// `Creating route ${routeId} with path ${route.path} using selector ${selector} (index ${selectorIndex})`, -// ); -// await createRoute( -// routeId, -// context.hostname, -// selector, -// route.path, -// route.routeSubpaths, -// route.stripPrefix !== undefined ? route.stripPrefix : true, -// ); -// context.routeIds.push(routeId); -// } -// } -// -// // Verify routes exist -// await verifyRouteExists(context.hostname); -// -// // Run the test function -// await testFn(context); -// -// // If we get here, the test passed -// console.log(`✅ Test "${config.name}" passed successfully`); -// return true; -// } catch (error) { -// console.error(`❌ Error in ${config.name}:`, error); -// return false; -// } finally { -// // Clean up all resources -// await cleanup(context); -// } -//} -// -//// Test implementations -//async function testBasicRoute(): Promise { -// return await setupTest( -// { -// name: "Basic Route Test", -// numSelectors: 1, -// routes: [ -// { -// path: "/test", -// routeSubpaths: false, -// stripPrefix: true, -// selectorIndex: 0, -// }, -// ], -// }, -// async (context) => { -// // Get the actor IDs for the first selector -// const selectorActors = -// context.actorsBySelector[context.selectors[0]]; -// const route = context.routes?.[0]; -// -// // Test the route -// const result = await testRoute( -// context.hostname, -// "/test", -// 2, -// 20, -// route, -// ); -// if (result.size < 2) { -// throw new Error( -// "Basic route test failed: Could not reach all expected actors", -// ); -// } -// -// // Verify we got responses from the correct actors -// let matchedActors = 0; -// for (const id of result) { -// if (selectorActors.includes(id)) { -// matchedActors++; -// } -// } -// -// if (matchedActors === result.size) { -// console.log("✅ All requests routed to the correct actors"); -// } else { -// console.log( -// `❌ Expected all requests to route to the correct actors, but only ${matchedActors}/${result.size} did`, -// ); -// throw new Error( -// `Basic route test failed: ${matchedActors}/${result.size} requests routed to the correct actors`, -// ); -// } -// }, -// ); -//} -// -//async function testPathPrefix(): Promise { -// return await setupTest( -// { -// name: "Path Prefix Test", -// numSelectors: 1, -// routes: [ -// { -// path: "/api", -// routeSubpaths: true, -// stripPrefix: true, -// selectorIndex: 0, -// }, -// ], -// }, -// async (context) => { -// // Get the actor IDs for the first selector -// const selectorActors = -// context.actorsBySelector[context.selectors[0]]; -// const route = context.routes?.[0]; -// -// // Test various paths that should match the prefix -// console.log("Testing paths that should match the prefix /api"); -// let result = await testRoute( -// context.hostname, -// "/api", -// 2, -// 20, -// route, -// ); -// if (result.size < 2) { -// throw new Error( -// "Path prefix test failed: Could not reach actors at /api", -// ); -// } -// -// result = await testRoute(context.hostname, "/api/v1", 2, 20, route); -// if (result.size < 2) { -// throw new Error( -// "Path prefix test failed: Could not reach actors at /api/v1", -// ); -// } -// -// result = await testRoute( -// context.hostname, -// "/api/users", -// 2, -// 20, -// route, -// ); -// if (result.size < 2) { -// throw new Error( -// "Path prefix test failed: Could not reach actors at /api/users", -// ); -// } -// -// // Test a path that shouldn't match -// console.log("Testing path that shouldn't match the prefix /api"); -// const nonMatchingResult = await testRoute( -// context.hostname, -// "/other", -// 2, -// 5, -// ); -// -// if (nonMatchingResult.size > 0) { -// console.log( -// "❌ Found match for non-matching path /other when it should have failed", -// ); -// throw new Error( -// "Path prefix test failed: Found match for non-matching path /other", -// ); -// } else { -// console.log( -// "✅ Correctly found no matches for non-matching path /other", -// ); -// } -// }, -// ); -//} -// -//async function testExactPath(): Promise { -// return await setupTest( -// { -// name: "Exact Path Test", -// numSelectors: 1, -// routes: [ -// { -// path: "/exact", -// routeSubpaths: false, -// stripPrefix: true, -// selectorIndex: 0, -// }, -// ], -// }, -// async (context) => { -// // Get the actor IDs for the selector -// const selectorActors = -// context.actorsBySelector[context.selectors[0]]; -// const route = context.routes?.[0]; -// -// // Test the exact path -// console.log("Testing exact path /exact"); -// const result = await testRoute( -// context.hostname, -// "/exact", -// 2, -// 20, -// route, -// ); -// if (result.size < 2) { -// throw new Error( -// "Exact path test failed: Could not reach actors at exact path /exact", -// ); -// } -// -// // Test paths that shouldn't match -// console.log( -// "Testing paths that shouldn't match the exact path /exact", -// ); -// const subPathResult = await testRoute( -// context.hostname, -// "/exact/subpath", -// 2, -// 5, -// ); -// -// if (subPathResult.size > 0) { -// console.log( -// "❌ Found match for /exact/subpath when it should have failed", -// ); -// throw new Error( -// "Exact path test failed: Found match for subpath /exact/subpath", -// ); -// } else { -// console.log("✅ Correctly found no matches for /exact/subpath"); -// } -// -// const differentPathResult = await testRoute( -// context.hostname, -// "/different", -// 2, -// 5, -// ); -// -// if (differentPathResult.size > 0) { -// console.log( -// "❌ Found match for /different when it should have failed", -// ); -// throw new Error( -// "Exact path test failed: Found match for different path /different", -// ); -// } else { -// console.log("✅ Correctly found no matches for /different"); -// } -// }, -// ); -//} -// -//async function testPathPriority(): Promise { -// return await setupTest( -// { -// name: "Path Priority Test", -// numSelectors: 2, -// routes: [ -// { -// path: "/api", -// routeSubpaths: true, -// stripPrefix: true, -// selectorIndex: 0, -// }, // Less specific path -// { -// path: "/api/users", -// routeSubpaths: true, -// stripPrefix: true, -// selectorIndex: 1, -// }, // More specific path (higher priority) -// ], -// }, -// async (context) => { -// // Get the selectors and actor groups -// const apiSelector = context.selectors[0]; -// const usersSelector = context.selectors[1]; -// -// const apiActors = context.actorsBySelector[apiSelector]; // API actors (lower priority) -// const usersActors = context.actorsBySelector[usersSelector]; // Users actors (higher priority) -// -// const apiRoute = context.routes?.[0]; -// const usersRoute = context.routes?.[1]; -// -// console.log( -// "API selector:", -// apiSelector, -// "with actors:", -// apiActors, -// ); -// console.log( -// "Users selector:", -// usersSelector, -// "with actors:", -// usersActors, -// ); -// -// // 1. First verify we can access both sets of actors directly with their exact paths -// console.log( -// "\nStep 1: Verifying direct access to both actor groups", -// ); -// -// // 1.1 Test the less specific path (/api) - should route to first set of actors -// console.log("Testing /api path - should route to API actors"); -// const apiResult = await testRoute( -// context.hostname, -// "/api", -// 2, -// 10, -// apiRoute, -// ); -// if (apiResult.size < 2) { -// throw new Error( -// "Path priority test failed: Could not reach actors at /api", -// ); -// } -// -// // Check we got responses from the API actors -// let matchedApiActors = 0; -// for (const id of apiResult) { -// if (apiActors.includes(id)) { -// matchedApiActors++; -// } -// } -// -// if (matchedApiActors === apiResult.size) { -// console.log( -// "✅ All requests to /api routed to API actors as expected", -// ); -// } else { -// console.log( -// `❌ Expected all requests to /api to route to API actors, but only ${matchedApiActors}/${apiResult.size} did`, -// ); -// throw new Error( -// `Path priority test failed: ${matchedApiActors}/${apiResult.size} requests to /api routed to API actors`, -// ); -// } -// -// // 1.2 Test the more specific path (/api/users) - should route to users actors -// console.log( -// "\nTesting /api/users path - should route to Users actors", -// ); -// const usersResult = await testRoute( -// context.hostname, -// "/api/users", -// 2, -// 10, -// usersRoute, -// ); -// if (usersResult.size < 2) { -// throw new Error( -// "Path priority test failed: Could not reach actors at /api/users", -// ); -// } -// -// // Check we got responses from the Users actors -// let matchedUsersActors = 0; -// for (const id of usersResult) { -// if (usersActors.includes(id)) { -// matchedUsersActors++; -// } -// } -// -// if (matchedUsersActors === usersResult.size) { -// console.log( -// "✅ All requests to /api/users routed to Users actors as expected", -// ); -// } else { -// console.log( -// `❌ Expected all requests to /api/users to route to Users actors, but only ${matchedUsersActors}/${usersResult.size} did`, -// ); -// throw new Error( -// `Path priority test failed: ${matchedUsersActors}/${usersResult.size} requests to /api/users routed to Users actors`, -// ); -// } -// -// // 2. Test a path that would match the /api prefix but is a subpath of /api/users -// // Should go to the /api/users actors as the more specific path has higher priority -// console.log("\nStep 2: Testing a subpath priority"); -// console.log( -// "Testing /api/users/123 path - should route to Users actors (more specific path)", -// ); -// const subpathResult = await testRoute( -// context.hostname, -// "/api/users/123", -// 2, -// 10, -// usersRoute, -// ); -// if (subpathResult.size < 2) { -// throw new Error( -// "Path priority test failed: Could not reach actors at /api/users/123", -// ); -// } -// -// // Check if we got responses from the expected actors (should be from Users actors path) -// let matchedSubpathUsers = 0; -// for (const id of subpathResult) { -// if (usersActors.includes(id)) { -// matchedSubpathUsers++; -// } -// } -// -// if (matchedSubpathUsers === subpathResult.size) { -// console.log( -// "✅ All requests for /api/users/123 routed to Users actors (more specific path) as expected", -// ); -// } else { -// console.log( -// `❌ Expected all requests to route to Users actors (more specific path), but only ${matchedSubpathUsers}/${subpathResult.size} did`, -// ); -// throw new Error( -// `Path priority test failed for subpath: ${matchedSubpathUsers}/${subpathResult.size} requests routed to the Users actors`, -// ); -// } -// -// // 3. Test a path that matches the /api prefix but is NOT a subpath of /api/users -// // Should go to the /api actors -// console.log("\nStep 3: Testing another /api subpath"); -// console.log( -// "Testing /api/other path - should route to API actors (because it's not under /api/users)", -// ); -// const otherResult = await testRoute( -// context.hostname, -// "/api/other", -// 2, -// 10, -// apiRoute, -// ); -// if (otherResult.size < 2) { -// throw new Error( -// "Path priority test failed: Could not reach actors at /api/other", -// ); -// } -// -// // Check if we got responses from the API actors -// let matchedOtherApi = 0; -// for (const id of otherResult) { -// if (apiActors.includes(id)) { -// matchedOtherApi++; -// } -// } -// -// if (matchedOtherApi === otherResult.size) { -// console.log( -// "✅ All requests for /api/other routed to API actors as expected", -// ); -// } else { -// console.log( -// `❌ Expected all requests to route to API actors, but only ${matchedOtherApi}/${otherResult.size} did`, -// ); -// throw new Error( -// `Path priority test failed for other subpath: ${matchedOtherApi}/${otherResult.size} requests routed to the API actors`, -// ); -// } -// }, -// ); -//} -// -//async function testEmptyPath(): Promise { -// return await setupTest( -// { -// name: "Empty Path Test", -// numSelectors: 1, -// routes: [ -// { -// path: "", -// routeSubpaths: true, -// stripPrefix: true, -// selectorIndex: 0, -// }, -// ], -// }, -// async (context) => { -// // Get the actor IDs for the first selector -// const selectorActors = -// context.actorsBySelector[context.selectors[0]]; -// const route = context.routes?.[0]; -// -// // Test various paths that should all match due to empty path with routeSubpaths=true -// console.log("Testing empty path which should match any path"); -// -// let result = await testRoute(context.hostname, "/", 2, 20, route); -// if (result.size < 2) { -// throw new Error( -// "Empty path test failed: Could not reach actors at /", -// ); -// } -// -// result = await testRoute(context.hostname, "/api", 2, 20, route); -// if (result.size < 2) { -// throw new Error( -// "Empty path test failed: Could not reach actors at /api", -// ); -// } -// -// result = await testRoute(context.hostname, "/users", 2, 20, route); -// if (result.size < 2) { -// throw new Error( -// "Empty path test failed: Could not reach actors at /users", -// ); -// } -// -// result = await testRoute( -// context.hostname, -// "/deep/nested/path", -// 2, -// 20, -// route, -// ); -// if (result.size < 2) { -// throw new Error( -// "Empty path test failed: Could not reach actors at /deep/nested/path", -// ); -// } -// }, -// ); -//} -// -//async function testNoStripPrefix(): Promise { -// return await setupTest( -// { -// name: "No Strip Prefix Test", -// numSelectors: 1, -// routes: [ -// { -// path: "/prefix", -// routeSubpaths: true, -// stripPrefix: false, -// selectorIndex: 0, -// }, -// ], -// }, -// async (context) => { -// // Get the actor IDs for the first selector -// const selectorActors = -// context.actorsBySelector[context.selectors[0]]; -// const route = context.routes?.[0]; -// -// // Test the exact path - the path in response should be the full path -// console.log( -// "Testing exact path with stripPrefix=false. Path should NOT be stripped.", -// ); -// const result = await testRoute( -// context.hostname, -// "/prefix", -// 2, -// 20, -// route, -// ); -// if (result.size < 2) { -// throw new Error( -// "No strip prefix test failed: Could not reach actors at /prefix", -// ); -// } -// -// // Test a subpath - the path in response should be the full path again -// console.log( -// "Testing subpath with stripPrefix=false. Path should NOT be stripped.", -// ); -// const subpathResult = await testRoute( -// context.hostname, -// "/prefix/subpath", -// 2, -// 20, -// route, -// ); -// if (subpathResult.size < 2) { -// throw new Error( -// "No strip prefix test failed: Could not reach actors at /prefix/subpath", -// ); -// } -// }, -// ); -//} -// -//async function testMultipleRoutes(): Promise { -// return await setupTest( -// { -// name: "Multiple Routes Test", -// numSelectors: 2, -// routes: [ -// { -// path: "/route1", -// routeSubpaths: false, -// stripPrefix: true, -// selectorIndex: 0, -// }, -// { -// path: "/route2", -// routeSubpaths: false, -// stripPrefix: true, -// selectorIndex: 1, -// }, -// ], -// }, -// async (context) => { -// // Get the actor IDs for both selectors -// const selector1Actors = -// context.actorsBySelector[context.selectors[0]]; -// const selector2Actors = -// context.actorsBySelector[context.selectors[1]]; -// -// const route1 = context.routes?.[0]; -// const route2 = context.routes?.[1]; -// -// // Test first route -// console.log("Testing first route /route1"); -// const result1 = await testRoute( -// context.hostname, -// "/route1", -// 2, -// 20, -// route1, -// ); -// if (result1.size < 2) { -// throw new Error( -// "Multiple routes test failed: Could not reach actors at /route1", -// ); -// } -// -// // Verify we got responses from the correct actors -// let matchedActors1 = 0; -// for (const id of result1) { -// if (selector1Actors.includes(id)) { -// matchedActors1++; -// } -// } -// -// if (matchedActors1 === result1.size) { -// console.log( -// "✅ All requests to /route1 routed to route1 actors as expected", -// ); -// } else { -// console.log( -// `❌ Expected all requests to route to route1 actors, but only ${matchedActors1}/${result1.size} did`, -// ); -// throw new Error( -// `Multiple routes test failed: ${matchedActors1}/${result1.size} requests to /route1 routed to route1 actors`, -// ); -// } -// -// // Test second route -// console.log("Testing second route /route2"); -// const result2 = await testRoute( -// context.hostname, -// "/route2", -// 2, -// 20, -// route2, -// ); -// if (result2.size < 2) { -// throw new Error( -// "Multiple routes test failed: Could not reach actors at /route2", -// ); -// } -// -// // Verify we got responses from the correct actors -// let matchedActors2 = 0; -// for (const id of result2) { -// if (selector2Actors.includes(id)) { -// matchedActors2++; -// } -// } -// -// if (matchedActors2 === result2.size) { -// console.log( -// "✅ All requests to /route2 routed to route2 actors as expected", -// ); -// } else { -// console.log( -// `❌ Expected all requests to route to route2 actors, but only ${matchedActors2}/${result2.size} did`, -// ); -// throw new Error( -// `Multiple routes test failed: ${matchedActors2}/${result2.size} requests to /route2 routed to route2 actors`, -// ); -// } -// }, -// ); -//} -// -//async function testQueryParameters(): Promise { -// return await setupTest( -// { -// name: "Query Parameters Test", -// numSelectors: 1, -// routes: [ -// { -// path: "/query", -// routeSubpaths: false, -// stripPrefix: true, -// selectorIndex: 0, -// }, -// ], -// }, -// async (context) => { -// // Get the actor IDs for the selector -// const selectorActors = -// context.actorsBySelector[context.selectors[0]]; -// const route = context.routes?.[0]; -// -// // Custom function to validate query parameters -// async function testWithQueryValidation( -// path: string, -// expectedQuery: Record, -// ): Promise { -// // Make the request -// const testUrl = `http://localhost:7080${path}`; -// console.log( -// `Testing route at: ${testUrl} (with Host: ${context.hostname})`, -// ); -// -// const data = await makeRequest(testUrl, context.hostname); -// if (!data) { -// throw new Error(`Failed to get response from ${path}`); -// } -// -// // Validate query parameters -// console.log("Expected query parameters:", expectedQuery); -// console.log("Actual query parameters:", data.query); -// -// // Check that all expected parameters are present -// let queryValidationPassed = true; -// for (const [key, value] of Object.entries(expectedQuery)) { -// if (data.query[key] !== value) { -// console.error( -// `❌ Query parameter validation failed for ${key}: Expected ${value}, got ${data.query[key]}`, -// ); -// queryValidationPassed = false; -// } -// } -// -// if (queryValidationPassed) { -// console.log("✅ Query parameter validation passed"); -// } else { -// throw new Error("Query parameter validation failed"); -// } -// } -// -// // Test path with simple query parameters -// console.log("Testing path with simple query parameters"); -// const result = await testRoute( -// context.hostname, -// "/query?param=value&another=123", -// 2, -// 20, -// route, -// ); -// if (result.size < 2) { -// throw new Error( -// "Query parameters test failed: Could not reach actors at /query with query parameters", -// ); -// } -// -// // Validate simple query parameters with direct check -// await testWithQueryValidation("/query?param=value&another=123", { -// param: "value", -// another: "123", -// }); -// -// // Test more complex query parameters -// console.log("Testing path with complex query parameters"); -// const complexResult = await testRoute( -// context.hostname, -// "/query?complex=test%20with%20spaces&array[]=1&array[]=2", -// 2, -// 20, -// route, -// ); -// if (complexResult.size < 2) { -// throw new Error( -// "Query parameters test failed: Could not reach actors at /query with complex query parameters", -// ); -// } -// -// // Validate complex query parameters with direct check -// await testWithQueryValidation( -// "/query?complex=test%20with%20spaces", -// { -// complex: "test with spaces", -// }, -// ); -// }, -// ); -//} -// -//async function testSpecialCharacters(): Promise { -// return await setupTest( -// { -// name: "Special Characters Test", -// numSelectors: 1, -// routes: [ -// { -// path: "/special-chars", -// routeSubpaths: true, -// stripPrefix: true, -// selectorIndex: 0, -// }, -// ], -// }, -// async (context) => { -// // Get the actor IDs for the selector -// const selectorActors = -// context.actorsBySelector[context.selectors[0]]; -// const route = context.routes?.[0]; -// -// // Test paths with special characters -// console.log("Testing path with hyphens"); -// let result = await testRoute( -// context.hostname, -// "/special-chars/with-hyphens", -// 2, -// 20, -// route, -// ); -// if (result.size < 2) { -// throw new Error( -// "Special characters test failed: Could not reach actors at path with hyphens", -// ); -// } -// -// console.log("Testing path with underscores"); -// result = await testRoute( -// context.hostname, -// "/special-chars/with_underscores", -// 2, -// 20, -// route, -// ); -// if (result.size < 2) { -// throw new Error( -// "Special characters test failed: Could not reach actors at path with underscores", -// ); -// } -// -// console.log("Testing path with dots"); -// result = await testRoute( -// context.hostname, -// "/special-chars/with.dots", -// 2, -// 20, -// route, -// ); -// if (result.size < 2) { -// throw new Error( -// "Special characters test failed: Could not reach actors at path with dots", -// ); -// } -// -// console.log("Testing path with encoded characters"); -// result = await testRoute( -// context.hostname, -// "/special-chars/encoded%20space", -// 2, -// 20, -// route, -// ); -// if (result.size < 2) { -// throw new Error( -// "Special characters test failed: Could not reach actors at path with encoded characters", -// ); -// } -// }, -// ); -//} -// -//async function testLargeActorPool(): Promise { -// return await setupTest( -// { -// name: "Large Actor Pool Test", -// numActors: 10, // Use 10 actors instead of the default 2 -// numSelectors: 1, -// routes: [ -// { -// path: "/large-pool", -// routeSubpaths: false, -// stripPrefix: true, -// selectorIndex: 0, -// }, -// ], -// }, -// async (context) => { -// // Get the actor IDs for the selector -// const selectorActors = -// context.actorsBySelector[context.selectors[0]]; -// const route = context.routes?.[0]; -// -// // Test with larger number of actors to verify load balancing -// console.log("Testing with larger actor pool (10 actors)"); -// -// // Make 20 requests and track unique actor IDs seen -// const allActorsResult = new Set(); -// -// // Make multiple requests to see distribution -// for (let i = 0; i < 3; i++) { -// console.log(`Batch ${i + 1} of requests to large actor pool:`); -// const result = await testRoute( -// context.hostname, -// "/large-pool", -// 5, -// 20, -// route, -// ); -// -// // Add these results to our overall set -// for (const id of result) { -// allActorsResult.add(id); -// } -// -// // Wait a bit between batches -// await new Promise((resolve) => setTimeout(resolve, 500)); -// } -// -// // Verify we've seen a good number of unique actors (at least 7 out of 10) -// if (allActorsResult.size < 7) { -// console.log( -// `❌ Only reached ${allActorsResult.size}/10 unique actors, expected at least 7`, -// ); -// throw new Error( -// `Large actor pool test: Only reached ${allActorsResult.size}/10 unique actors`, -// ); -// } else { -// console.log( -// `✅ Reached ${allActorsResult.size}/10 unique actors across all requests`, -// ); -// } -// }, -// ); -//} -// -//async function testLongPath(): Promise { -// return await setupTest( -// { -// name: "Long Path Test", -// numSelectors: 1, -// routes: [ -// { -// path: "/long", -// routeSubpaths: true, -// stripPrefix: true, -// selectorIndex: 0, -// }, -// ], -// }, -// async (context) => { -// // Get the actor IDs for the selector -// const selectorActors = -// context.actorsBySelector[context.selectors[0]]; -// const route = context.routes?.[0]; -// -// // Create a very long path -// let longPathSegment = ""; -// for (let i = 0; i < 10; i++) { -// longPathSegment += "segment-" + i + "/"; -// } -// const longPath = `/long/${longPathSegment}end`; -// -// console.log("Testing very long path"); -// console.log(`Path length: ${longPath.length} characters`); -// -// const result = await testRoute( -// context.hostname, -// longPath, -// 2, -// 20, -// route, -// ); -// if (result.size < 2) { -// throw new Error( -// "Long path test failed: Could not reach actors with very long path", -// ); -// } -// }, -// ); -//} -// -//async function testMixedPrefixStripping(): Promise { -// return await setupTest( -// { -// name: "Mixed Prefix Stripping Test", -// numSelectors: 2, -// routes: [ -// { -// path: "/strip", -// routeSubpaths: true, -// stripPrefix: true, -// selectorIndex: 0, -// }, -// { -// path: "/nostrip", -// routeSubpaths: true, -// stripPrefix: false, -// selectorIndex: 1, -// }, -// ], -// }, -// async (context) => { -// // Get the actor IDs for both selectors -// const stripActors = context.actorsBySelector[context.selectors[0]]; -// const noStripActors = -// context.actorsBySelector[context.selectors[1]]; -// -// const stripRoute = context.routes?.[0]; -// const noStripRoute = context.routes?.[1]; -// -// // Test the strip prefix route -// console.log("Testing route with stripPrefix=true"); -// const stripResult = await testRoute( -// context.hostname, -// "/strip/subpath", -// 2, -// 20, -// stripRoute, -// ); -// if (stripResult.size < 2) { -// throw new Error( -// "Mixed prefix stripping test failed: Could not reach actors at /strip/subpath", -// ); -// } -// -// // Test the no strip prefix route -// console.log("Testing route with stripPrefix=false"); -// const noStripResult = await testRoute( -// context.hostname, -// "/nostrip/subpath", -// 2, -// 20, -// noStripRoute, -// ); -// if (noStripResult.size < 2) { -// throw new Error( -// "Mixed prefix stripping test failed: Could not reach actors at /nostrip/subpath", -// ); -// } -// -// // Verify we got responses from the correct actors for strip route -// let matchedStripActors = 0; -// for (const id of stripResult) { -// if (stripActors.includes(id)) { -// matchedStripActors++; -// } -// } -// -// if (matchedStripActors === stripResult.size) { -// console.log( -// "✅ All requests to /strip/subpath routed to strip actors as expected", -// ); -// } else { -// console.log( -// `❌ Expected all requests to route to strip actors, but only ${matchedStripActors}/${stripResult.size} did`, -// ); -// throw new Error( -// `Mixed prefix stripping test failed: ${matchedStripActors}/${stripResult.size} requests routed to strip actors`, -// ); -// } -// -// // Verify we got responses from the correct actors for no-strip route -// let matchedNoStripActors = 0; -// for (const id of noStripResult) { -// if (noStripActors.includes(id)) { -// matchedNoStripActors++; -// } -// } -// -// if (matchedNoStripActors === noStripResult.size) { -// console.log( -// "✅ All requests to /nostrip/subpath routed to no-strip actors as expected", -// ); -// } else { -// console.log( -// `❌ Expected all requests to route to no-strip actors, but only ${matchedNoStripActors}/${noStripResult.size} did`, -// ); -// throw new Error( -// `Mixed prefix stripping test failed: ${matchedNoStripActors}/${noStripResult.size} requests routed to no-strip actors`, -// ); -// } -// }, -// ); -//} -// -//async function test404Response(): Promise { -// return await setupTest( -// { -// name: "404 Response Test", -// numSelectors: 1, -// routes: [ -// { -// path: "/test-path", -// routeSubpaths: false, -// stripPrefix: true, -// selectorIndex: 0, -// }, -// ], -// }, -// async (context) => { -// // Get the actor IDs for the selector -// const selectorActors = -// context.actorsBySelector[context.selectors[0]]; -// const route = context.routes?.[0]; -// -// // First verify our route works -// console.log("Verifying route /test-path exists and works"); -// const result = await testRoute( -// context.hostname, -// "/test-path", -// 2, -// 20, -// route, -// ); -// if (result.size < 2) { -// throw new Error( -// "404 test setup failed: Could not reach actors at /test-path", -// ); -// } -// -// // Now test a path that doesn't match any route - should return 404 -// console.log("Testing path that should 404: /non-existent-path"); -// -// try { -// // We expect this to return an empty set (no matches) -// const notFoundResult = await testRoute( -// context.hostname, -// "/non-existent-path", -// 2, -// 5, -// ); -// -// // If we get here with results, it means the 404 test failed -// if (notFoundResult.size > 0) { -// console.error( -// "❌ Expected 404 for /non-existent-path but got a successful response", -// ); -// throw new Error( -// "404 test failed: Got a successful response instead of 404", -// ); -// } else { -// console.log( -// "✅ Correctly received no matches for non-existent path", -// ); -// } -// } catch (error) { -// // Check if this is our expected path validation error -// if ( -// error instanceof Error && -// error.message.includes("Path validation failed") -// ) { -// console.error( -// "❌ Unexpected path returned for non-existent route", -// ); -// throw error; -// } -// -// // If it's a different error (like connection refused), that's expected for a 404 -// console.log( -// "✅ Received expected error for non-existent path:", -// error.message, -// ); -// } -// -// // Test with a different hostname that doesn't have any routes -// const randomHostname = `nonexistent-${crypto.randomBytes(4).toString("hex")}.rivet-job.local`; -// console.log("Testing with non-existent hostname:", randomHostname); -// -// try { -// const nonExistentHostResult = await makeRequest( -// `http://localhost:7080/test`, -// randomHostname, -// ); -// -// // If we get a response, it's unexpected -// if (nonExistentHostResult) { -// console.error( -// "❌ Expected 404 for non-existent hostname but got a response:", -// nonExistentHostResult, -// ); -// throw new Error( -// "404 test failed: Got a response for non-existent hostname", -// ); -// } else { -// console.log( -// "✅ Correctly received no response for non-existent hostname", -// ); -// } -// } catch (error) { -// // This is expected - we should get an error -// console.log( -// "✅ Received expected error for non-existent hostname:", -// error.message, -// ); -// } -// }, -// ); -//} -// -//async function run() { -// try { -// const tests = [ -// { name: "Basic Route Test", fn: testBasicRoute }, -// { name: "Path Prefix Test", fn: testPathPrefix }, -// { name: "Exact Path Test", fn: testExactPath }, -// { name: "Path Priority Test", fn: testPathPriority }, -// { name: "Empty Path Test", fn: testEmptyPath }, -// { name: "No Strip Prefix Test", fn: testNoStripPrefix }, -// { name: "Multiple Routes Test", fn: testMultipleRoutes }, -// { name: "Query Parameters Test", fn: testQueryParameters }, -// { name: "Special Characters Test", fn: testSpecialCharacters }, -// { name: "Large Actor Pool Test", fn: testLargeActorPool }, -// { name: "Long Path Test", fn: testLongPath }, -// { -// name: "Mixed Prefix Stripping Test", -// fn: testMixedPrefixStripping, -// }, -// { name: "404 Response Test", fn: test404Response }, // 404 test should run last -// ]; -// -// for (const test of tests) { -// console.log(`\nRunning test: ${test.name}`); -// const testPassed = await test.fn(); -// -// // If any test fails, exit immediately -// if (!testPassed) { -// console.error( -// `\n❌ Test "${test.name}" failed. Exiting test suite.`, -// ); -// process.exit(1); -// } -// } -// -// console.log("\n=== All tests completed successfully ===\n"); -// process.exit(0); -// } catch (error) { -// console.error("Error running tests:", error); -// process.exit(1); -// } -//} -// -//// Run the test -//run().catch((error) => { -// console.error("Unhandled error in test suite:", error); -// process.exit(1); -//}); diff --git a/examples/system-test-route/tsconfig.json b/examples/system-test-route/tsconfig.json deleted file mode 100644 index f5113240c4..0000000000 --- a/examples/system-test-route/tsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "module": "NodeNext", - "moduleResolution": "NodeNext", - "types": ["node", "deno"], - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - "isolatedModules": true, - "strict": true, - "skipLibCheck": true, - "outDir": "dist" - }, - "include": ["**/*.ts"], - "exclude": ["node_modules", "dist"] -} diff --git a/examples/system-test-route/yarn.lock b/examples/system-test-route/yarn.lock deleted file mode 100644 index 973d700871..0000000000 --- a/examples/system-test-route/yarn.lock +++ /dev/null @@ -1,1325 +0,0 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 8 - cacheKey: 10c0 - -"@esbuild/aix-ppc64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/aix-ppc64@npm:0.25.5" - conditions: os=aix & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/android-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/android-arm64@npm:0.25.5" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/android-arm@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/android-arm@npm:0.25.5" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - -"@esbuild/android-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/android-x64@npm:0.25.5" - conditions: os=android & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/darwin-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/darwin-arm64@npm:0.25.5" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/darwin-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/darwin-x64@npm:0.25.5" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/freebsd-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/freebsd-arm64@npm:0.25.5" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/freebsd-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/freebsd-x64@npm:0.25.5" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/linux-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-arm64@npm:0.25.5" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/linux-arm@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-arm@npm:0.25.5" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@esbuild/linux-ia32@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-ia32@npm:0.25.5" - conditions: os=linux & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/linux-loong64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-loong64@npm:0.25.5" - conditions: os=linux & cpu=loong64 - languageName: node - linkType: hard - -"@esbuild/linux-mips64el@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-mips64el@npm:0.25.5" - conditions: os=linux & cpu=mips64el - languageName: node - linkType: hard - -"@esbuild/linux-ppc64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-ppc64@npm:0.25.5" - conditions: os=linux & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/linux-riscv64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-riscv64@npm:0.25.5" - conditions: os=linux & cpu=riscv64 - languageName: node - linkType: hard - -"@esbuild/linux-s390x@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-s390x@npm:0.25.5" - conditions: os=linux & cpu=s390x - languageName: node - linkType: hard - -"@esbuild/linux-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/linux-x64@npm:0.25.5" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/netbsd-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/netbsd-arm64@npm:0.25.5" - conditions: os=netbsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/netbsd-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/netbsd-x64@npm:0.25.5" - conditions: os=netbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/openbsd-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/openbsd-arm64@npm:0.25.5" - conditions: os=openbsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/openbsd-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/openbsd-x64@npm:0.25.5" - conditions: os=openbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/sunos-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/sunos-x64@npm:0.25.5" - conditions: os=sunos & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/win32-arm64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/win32-arm64@npm:0.25.5" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/win32-ia32@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/win32-ia32@npm:0.25.5" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/win32-x64@npm:0.25.5": - version: 0.25.5 - resolution: "@esbuild/win32-x64@npm:0.25.5" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@hono/node-server@npm:^1.13.8": - version: 1.14.3 - resolution: "@hono/node-server@npm:1.14.3" - peerDependencies: - hono: ^4 - checksum: 10c0/2e873ed38be44bd2499ffd6e592782edd9216475935d992119ad1d3f61f14cb39dc8fe79d1ed5d7d8caeef1d9fd84b36f9715add0b9f98c3d040b5cc9ef872f8 - languageName: node - linkType: hard - -"@hono/node-ws@npm:^1.1.0": - version: 1.1.6 - resolution: "@hono/node-ws@npm:1.1.6" - dependencies: - ws: "npm:^8.17.0" - peerDependencies: - "@hono/node-server": ^1.11.1 - hono: ^4.6.0 - checksum: 10c0/3995341e8b6e6a0e67ac11e54c42f2d6a84e1379ed0c2ce8af1a79128b1815b8cc9beb65e7917faa43a623ead7a27adf9cb3a0584377190bde287714cc2c10a0 - languageName: node - linkType: hard - -"@isaacs/cliui@npm:^8.0.2": - version: 8.0.2 - resolution: "@isaacs/cliui@npm:8.0.2" - dependencies: - string-width: "npm:^5.1.2" - string-width-cjs: "npm:string-width@^4.2.0" - strip-ansi: "npm:^7.0.1" - strip-ansi-cjs: "npm:strip-ansi@^6.0.1" - wrap-ansi: "npm:^8.1.0" - wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" - checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e - languageName: node - linkType: hard - -"@isaacs/fs-minipass@npm:^4.0.0": - version: 4.0.1 - resolution: "@isaacs/fs-minipass@npm:4.0.1" - dependencies: - minipass: "npm:^7.0.4" - checksum: 10c0/c25b6dc1598790d5b55c0947a9b7d111cfa92594db5296c3b907e2f533c033666f692a3939eadac17b1c7c40d362d0b0635dc874cbfe3e70db7c2b07cc97a5d2 - languageName: node - linkType: hard - -"@npmcli/agent@npm:^3.0.0": - version: 3.0.0 - resolution: "@npmcli/agent@npm:3.0.0" - dependencies: - agent-base: "npm:^7.1.0" - http-proxy-agent: "npm:^7.0.0" - https-proxy-agent: "npm:^7.0.1" - lru-cache: "npm:^10.0.1" - socks-proxy-agent: "npm:^8.0.3" - checksum: 10c0/efe37b982f30740ee77696a80c196912c274ecd2cb243bc6ae7053a50c733ce0f6c09fda085145f33ecf453be19654acca74b69e81eaad4c90f00ccffe2f9271 - languageName: node - linkType: hard - -"@npmcli/fs@npm:^4.0.0": - version: 4.0.0 - resolution: "@npmcli/fs@npm:4.0.0" - dependencies: - semver: "npm:^7.3.5" - checksum: 10c0/c90935d5ce670c87b6b14fab04a965a3b8137e585f8b2a6257263bd7f97756dd736cb165bb470e5156a9e718ecd99413dccc54b1138c1a46d6ec7cf325982fe5 - languageName: node - linkType: hard - -"@pkgjs/parseargs@npm:^0.11.0": - version: 0.11.0 - resolution: "@pkgjs/parseargs@npm:0.11.0" - checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd - languageName: node - linkType: hard - -"@rivet-gg/actor-core@npm:^5.1.2": - version: 5.1.3 - resolution: "@rivet-gg/actor-core@npm:5.1.3" - dependencies: - zod: "npm:^3.24.1" - checksum: 10c0/9723a95f2fc0701b8ebe2743378d49d9b37ffc8055cbdbf8dd7ff3ba40484c4b7e0c20caa3d34e1aed07d0a96adf654d417593fae2d01204d34bbe2a09f51a1d - languageName: node - linkType: hard - -"@types/deno@npm:^2.2.0": - version: 2.3.0 - resolution: "@types/deno@npm:2.3.0" - checksum: 10c0/7b4c9a2f905f1e737dcafffc8475575bd1647cbc3da140d71965f9a3289e34b6f3f2dc71c1e28f664aba6e999c0e9499d522329f734822bc4b11dd2c4f6342bc - languageName: node - linkType: hard - -"@types/node@npm:*, @types/node@npm:^22.13.9": - version: 22.15.29 - resolution: "@types/node@npm:22.15.29" - dependencies: - undici-types: "npm:~6.21.0" - checksum: 10c0/602cc88c6150780cd9b5b44604754e0ce13983ae876a538861d6ecfb1511dff289e5576fffd26c841cde2142418d4bb76e2a72a382b81c04557ccb17cff29e1d - languageName: node - linkType: hard - -"@types/ws@npm:^8.18.0": - version: 8.18.1 - resolution: "@types/ws@npm:8.18.1" - dependencies: - "@types/node": "npm:*" - checksum: 10c0/61aff1129143fcc4312f083bc9e9e168aa3026b7dd6e70796276dcfb2c8211c4292603f9c4864fae702f2ed86e4abd4d38aa421831c2fd7f856c931a481afbab - languageName: node - linkType: hard - -"abbrev@npm:^3.0.0": - version: 3.0.1 - resolution: "abbrev@npm:3.0.1" - checksum: 10c0/21ba8f574ea57a3106d6d35623f2c4a9111d9ee3e9a5be47baed46ec2457d2eac46e07a5c4a60186f88cb98abbe3e24f2d4cca70bc2b12f1692523e2209a9ccf - languageName: node - linkType: hard - -"agent-base@npm:^7.1.0, agent-base@npm:^7.1.2": - version: 7.1.3 - resolution: "agent-base@npm:7.1.3" - checksum: 10c0/6192b580c5b1d8fb399b9c62bf8343d76654c2dd62afcb9a52b2cf44a8b6ace1e3b704d3fe3547d91555c857d3df02603341ff2cb961b9cfe2b12f9f3c38ee11 - languageName: node - linkType: hard - -"ansi-regex@npm:^5.0.1": - version: 5.0.1 - resolution: "ansi-regex@npm:5.0.1" - checksum: 10c0/9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737 - languageName: node - linkType: hard - -"ansi-regex@npm:^6.0.1": - version: 6.1.0 - resolution: "ansi-regex@npm:6.1.0" - checksum: 10c0/a91daeddd54746338478eef88af3439a7edf30f8e23196e2d6ed182da9add559c601266dbef01c2efa46a958ad6f1f8b176799657616c702b5b02e799e7fd8dc - languageName: node - linkType: hard - -"ansi-styles@npm:^4.0.0": - version: 4.3.0 - resolution: "ansi-styles@npm:4.3.0" - dependencies: - color-convert: "npm:^2.0.1" - checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 - languageName: node - linkType: hard - -"ansi-styles@npm:^6.1.0": - version: 6.2.1 - resolution: "ansi-styles@npm:6.2.1" - checksum: 10c0/5d1ec38c123984bcedd996eac680d548f31828bd679a66db2bdf11844634dde55fec3efa9c6bb1d89056a5e79c1ac540c4c784d592ea1d25028a92227d2f2d5c - languageName: node - linkType: hard - -"balanced-match@npm:^1.0.0": - version: 1.0.2 - resolution: "balanced-match@npm:1.0.2" - checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee - languageName: node - linkType: hard - -"brace-expansion@npm:^2.0.1": - version: 2.0.1 - resolution: "brace-expansion@npm:2.0.1" - dependencies: - balanced-match: "npm:^1.0.0" - checksum: 10c0/b358f2fe060e2d7a87aa015979ecea07f3c37d4018f8d6deb5bd4c229ad3a0384fe6029bb76cd8be63c81e516ee52d1a0673edbe2023d53a5191732ae3c3e49f - languageName: node - linkType: hard - -"cacache@npm:^19.0.1": - version: 19.0.1 - resolution: "cacache@npm:19.0.1" - dependencies: - "@npmcli/fs": "npm:^4.0.0" - fs-minipass: "npm:^3.0.0" - glob: "npm:^10.2.2" - lru-cache: "npm:^10.0.1" - minipass: "npm:^7.0.3" - minipass-collect: "npm:^2.0.1" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.4" - p-map: "npm:^7.0.2" - ssri: "npm:^12.0.0" - tar: "npm:^7.4.3" - unique-filename: "npm:^4.0.0" - checksum: 10c0/01f2134e1bd7d3ab68be851df96c8d63b492b1853b67f2eecb2c37bb682d37cb70bb858a16f2f0554d3c0071be6dfe21456a1ff6fa4b7eed996570d6a25ffe9c - languageName: node - linkType: hard - -"chownr@npm:^3.0.0": - version: 3.0.0 - resolution: "chownr@npm:3.0.0" - checksum: 10c0/43925b87700f7e3893296c8e9c56cc58f926411cce3a6e5898136daaf08f08b9a8eb76d37d3267e707d0dcc17aed2e2ebdf5848c0c3ce95cf910a919935c1b10 - languageName: node - linkType: hard - -"color-convert@npm:^2.0.1": - version: 2.0.1 - resolution: "color-convert@npm:2.0.1" - dependencies: - color-name: "npm:~1.1.4" - checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 - languageName: node - linkType: hard - -"color-name@npm:~1.1.4": - version: 1.1.4 - resolution: "color-name@npm:1.1.4" - checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 - languageName: node - linkType: hard - -"cross-spawn@npm:^7.0.6": - version: 7.0.6 - resolution: "cross-spawn@npm:7.0.6" - dependencies: - path-key: "npm:^3.1.0" - shebang-command: "npm:^2.0.0" - which: "npm:^2.0.1" - checksum: 10c0/053ea8b2135caff68a9e81470e845613e374e7309a47731e81639de3eaeb90c3d01af0e0b44d2ab9d50b43467223b88567dfeb3262db942dc063b9976718ffc1 - languageName: node - linkType: hard - -"data-uri-to-buffer@npm:^4.0.0": - version: 4.0.1 - resolution: "data-uri-to-buffer@npm:4.0.1" - checksum: 10c0/20a6b93107597530d71d4cb285acee17f66bcdfc03fd81040921a81252f19db27588d87fc8fc69e1950c55cfb0bf8ae40d0e5e21d907230813eb5d5a7f9eb45b - languageName: node - linkType: hard - -"debug@npm:4, debug@npm:^4.3.4": - version: 4.4.1 - resolution: "debug@npm:4.4.1" - dependencies: - ms: "npm:^2.1.3" - peerDependenciesMeta: - supports-color: - optional: true - checksum: 10c0/d2b44bc1afd912b49bb7ebb0d50a860dc93a4dd7d946e8de94abc957bb63726b7dd5aa48c18c2386c379ec024c46692e15ed3ed97d481729f929201e671fcd55 - languageName: node - linkType: hard - -"eastasianwidth@npm:^0.2.0": - version: 0.2.0 - resolution: "eastasianwidth@npm:0.2.0" - checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 - languageName: node - linkType: hard - -"emoji-regex@npm:^8.0.0": - version: 8.0.0 - resolution: "emoji-regex@npm:8.0.0" - checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 - languageName: node - linkType: hard - -"emoji-regex@npm:^9.2.2": - version: 9.2.2 - resolution: "emoji-regex@npm:9.2.2" - checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 - languageName: node - linkType: hard - -"encoding@npm:^0.1.13": - version: 0.1.13 - resolution: "encoding@npm:0.1.13" - dependencies: - iconv-lite: "npm:^0.6.2" - checksum: 10c0/36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039 - languageName: node - linkType: hard - -"env-paths@npm:^2.2.0": - version: 2.2.1 - resolution: "env-paths@npm:2.2.1" - checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 - languageName: node - linkType: hard - -"err-code@npm:^2.0.2": - version: 2.0.3 - resolution: "err-code@npm:2.0.3" - checksum: 10c0/b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66 - languageName: node - linkType: hard - -"esbuild@npm:~0.25.0": - version: 0.25.5 - resolution: "esbuild@npm:0.25.5" - dependencies: - "@esbuild/aix-ppc64": "npm:0.25.5" - "@esbuild/android-arm": "npm:0.25.5" - "@esbuild/android-arm64": "npm:0.25.5" - "@esbuild/android-x64": "npm:0.25.5" - "@esbuild/darwin-arm64": "npm:0.25.5" - "@esbuild/darwin-x64": "npm:0.25.5" - "@esbuild/freebsd-arm64": "npm:0.25.5" - "@esbuild/freebsd-x64": "npm:0.25.5" - "@esbuild/linux-arm": "npm:0.25.5" - "@esbuild/linux-arm64": "npm:0.25.5" - "@esbuild/linux-ia32": "npm:0.25.5" - "@esbuild/linux-loong64": "npm:0.25.5" - "@esbuild/linux-mips64el": "npm:0.25.5" - "@esbuild/linux-ppc64": "npm:0.25.5" - "@esbuild/linux-riscv64": "npm:0.25.5" - "@esbuild/linux-s390x": "npm:0.25.5" - "@esbuild/linux-x64": "npm:0.25.5" - "@esbuild/netbsd-arm64": "npm:0.25.5" - "@esbuild/netbsd-x64": "npm:0.25.5" - "@esbuild/openbsd-arm64": "npm:0.25.5" - "@esbuild/openbsd-x64": "npm:0.25.5" - "@esbuild/sunos-x64": "npm:0.25.5" - "@esbuild/win32-arm64": "npm:0.25.5" - "@esbuild/win32-ia32": "npm:0.25.5" - "@esbuild/win32-x64": "npm:0.25.5" - dependenciesMeta: - "@esbuild/aix-ppc64": - optional: true - "@esbuild/android-arm": - optional: true - "@esbuild/android-arm64": - optional: true - "@esbuild/android-x64": - optional: true - "@esbuild/darwin-arm64": - optional: true - "@esbuild/darwin-x64": - optional: true - "@esbuild/freebsd-arm64": - optional: true - "@esbuild/freebsd-x64": - optional: true - "@esbuild/linux-arm": - optional: true - "@esbuild/linux-arm64": - optional: true - "@esbuild/linux-ia32": - optional: true - "@esbuild/linux-loong64": - optional: true - "@esbuild/linux-mips64el": - optional: true - "@esbuild/linux-ppc64": - optional: true - "@esbuild/linux-riscv64": - optional: true - "@esbuild/linux-s390x": - optional: true - "@esbuild/linux-x64": - optional: true - "@esbuild/netbsd-arm64": - optional: true - "@esbuild/netbsd-x64": - optional: true - "@esbuild/openbsd-arm64": - optional: true - "@esbuild/openbsd-x64": - optional: true - "@esbuild/sunos-x64": - optional: true - "@esbuild/win32-arm64": - optional: true - "@esbuild/win32-ia32": - optional: true - "@esbuild/win32-x64": - optional: true - bin: - esbuild: bin/esbuild - checksum: 10c0/aba8cbc11927fa77562722ed5e95541ce2853f67ad7bdc40382b558abc2e0ec57d92ffb820f082ba2047b4ef9f3bc3da068cdebe30dfd3850cfa3827a78d604e - languageName: node - linkType: hard - -"exponential-backoff@npm:^3.1.1": - version: 3.1.2 - resolution: "exponential-backoff@npm:3.1.2" - checksum: 10c0/d9d3e1eafa21b78464297df91f1776f7fbaa3d5e3f7f0995648ca5b89c069d17055033817348d9f4a43d1c20b0eab84f75af6991751e839df53e4dfd6f22e844 - languageName: node - linkType: hard - -"fdir@npm:^6.4.4": - version: 6.4.5 - resolution: "fdir@npm:6.4.5" - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - checksum: 10c0/5d63330a1b97165e9b0fb20369fafc7cf826bc4b3e374efcb650bc77d7145ac01193b5da1a7591eab89ae6fd6b15cdd414085910b2a2b42296b1480c9f2677af - languageName: node - linkType: hard - -"fetch-blob@npm:^3.1.2, fetch-blob@npm:^3.1.4": - version: 3.2.0 - resolution: "fetch-blob@npm:3.2.0" - dependencies: - node-domexception: "npm:^1.0.0" - web-streams-polyfill: "npm:^3.0.3" - checksum: 10c0/60054bf47bfa10fb0ba6cb7742acec2f37c1f56344f79a70bb8b1c48d77675927c720ff3191fa546410a0442c998d27ab05e9144c32d530d8a52fbe68f843b69 - languageName: node - linkType: hard - -"foreground-child@npm:^3.1.0": - version: 3.3.1 - resolution: "foreground-child@npm:3.3.1" - dependencies: - cross-spawn: "npm:^7.0.6" - signal-exit: "npm:^4.0.1" - checksum: 10c0/8986e4af2430896e65bc2788d6679067294d6aee9545daefc84923a0a4b399ad9c7a3ea7bd8c0b2b80fdf4a92de4c69df3f628233ff3224260e9c1541a9e9ed3 - languageName: node - linkType: hard - -"formdata-polyfill@npm:^4.0.10": - version: 4.0.10 - resolution: "formdata-polyfill@npm:4.0.10" - dependencies: - fetch-blob: "npm:^3.1.2" - checksum: 10c0/5392ec484f9ce0d5e0d52fb5a78e7486637d516179b0eb84d81389d7eccf9ca2f663079da56f761355c0a65792810e3b345dc24db9a8bbbcf24ef3c8c88570c6 - languageName: node - linkType: hard - -"fs-minipass@npm:^3.0.0": - version: 3.0.3 - resolution: "fs-minipass@npm:3.0.3" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94 - languageName: node - linkType: hard - -"fsevents@npm:~2.3.3": - version: 2.3.3 - resolution: "fsevents@npm:2.3.3" - dependencies: - node-gyp: "npm:latest" - checksum: 10c0/a1f0c44595123ed717febbc478aa952e47adfc28e2092be66b8ab1635147254ca6cfe1df792a8997f22716d4cbafc73309899ff7bfac2ac3ad8cf2e4ecc3ec60 - conditions: os=darwin - languageName: node - linkType: hard - -"fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": - version: 2.3.3 - resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" - dependencies: - node-gyp: "npm:latest" - conditions: os=darwin - languageName: node - linkType: hard - -"get-tsconfig@npm:^4.7.5": - version: 4.10.1 - resolution: "get-tsconfig@npm:4.10.1" - dependencies: - resolve-pkg-maps: "npm:^1.0.0" - checksum: 10c0/7f8e3dabc6a49b747920a800fb88e1952fef871cdf51b79e98db48275a5de6cdaf499c55ee67df5fa6fe7ce65f0063e26de0f2e53049b408c585aa74d39ffa21 - languageName: node - linkType: hard - -"glob@npm:^10.2.2": - version: 10.4.5 - resolution: "glob@npm:10.4.5" - dependencies: - foreground-child: "npm:^3.1.0" - jackspeak: "npm:^3.1.2" - minimatch: "npm:^9.0.4" - minipass: "npm:^7.1.2" - package-json-from-dist: "npm:^1.0.0" - path-scurry: "npm:^1.11.1" - bin: - glob: dist/esm/bin.mjs - checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e - languageName: node - linkType: hard - -"graceful-fs@npm:^4.2.6": - version: 4.2.11 - resolution: "graceful-fs@npm:4.2.11" - checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 - languageName: node - linkType: hard - -"hono@npm:^4.6.17": - version: 4.7.11 - resolution: "hono@npm:4.7.11" - checksum: 10c0/2821471b09f2e9f7bab5ad7412e2e44df5f07b7098508d70dd6e368b933580f03a06c30e20dd764b53e0121e1b1ff2132ae98cffa7fd1b286e299f9054effd6a - languageName: node - linkType: hard - -"http-cache-semantics@npm:^4.1.1": - version: 4.2.0 - resolution: "http-cache-semantics@npm:4.2.0" - checksum: 10c0/45b66a945cf13ec2d1f29432277201313babf4a01d9e52f44b31ca923434083afeca03f18417f599c9ab3d0e7b618ceb21257542338b57c54b710463b4a53e37 - languageName: node - linkType: hard - -"http-proxy-agent@npm:^7.0.0": - version: 7.0.2 - resolution: "http-proxy-agent@npm:7.0.2" - dependencies: - agent-base: "npm:^7.1.0" - debug: "npm:^4.3.4" - checksum: 10c0/4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921 - languageName: node - linkType: hard - -"https-proxy-agent@npm:^7.0.1": - version: 7.0.6 - resolution: "https-proxy-agent@npm:7.0.6" - dependencies: - agent-base: "npm:^7.1.2" - debug: "npm:4" - checksum: 10c0/f729219bc735edb621fa30e6e84e60ee5d00802b8247aac0d7b79b0bd6d4b3294737a337b93b86a0bd9e68099d031858a39260c976dc14cdbba238ba1f8779ac - languageName: node - linkType: hard - -"iconv-lite@npm:^0.6.2": - version: 0.6.3 - resolution: "iconv-lite@npm:0.6.3" - dependencies: - safer-buffer: "npm:>= 2.1.2 < 3.0.0" - checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 - languageName: node - linkType: hard - -"imurmurhash@npm:^0.1.4": - version: 0.1.4 - resolution: "imurmurhash@npm:0.1.4" - checksum: 10c0/8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 - languageName: node - linkType: hard - -"ip-address@npm:^9.0.5": - version: 9.0.5 - resolution: "ip-address@npm:9.0.5" - dependencies: - jsbn: "npm:1.1.0" - sprintf-js: "npm:^1.1.3" - checksum: 10c0/331cd07fafcb3b24100613e4b53e1a2b4feab11e671e655d46dc09ee233da5011284d09ca40c4ecbdfe1d0004f462958675c224a804259f2f78d2465a87824bc - languageName: node - linkType: hard - -"is-fullwidth-code-point@npm:^3.0.0": - version: 3.0.0 - resolution: "is-fullwidth-code-point@npm:3.0.0" - checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc - languageName: node - linkType: hard - -"isexe@npm:^2.0.0": - version: 2.0.0 - resolution: "isexe@npm:2.0.0" - checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d - languageName: node - linkType: hard - -"isexe@npm:^3.1.1": - version: 3.1.1 - resolution: "isexe@npm:3.1.1" - checksum: 10c0/9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7 - languageName: node - linkType: hard - -"jackspeak@npm:^3.1.2": - version: 3.4.3 - resolution: "jackspeak@npm:3.4.3" - dependencies: - "@isaacs/cliui": "npm:^8.0.2" - "@pkgjs/parseargs": "npm:^0.11.0" - dependenciesMeta: - "@pkgjs/parseargs": - optional: true - checksum: 10c0/6acc10d139eaefdbe04d2f679e6191b3abf073f111edf10b1de5302c97ec93fffeb2fdd8681ed17f16268aa9dd4f8c588ed9d1d3bffbbfa6e8bf897cbb3149b9 - languageName: node - linkType: hard - -"jsbn@npm:1.1.0": - version: 1.1.0 - resolution: "jsbn@npm:1.1.0" - checksum: 10c0/4f907fb78d7b712e11dea8c165fe0921f81a657d3443dde75359ed52eb2b5d33ce6773d97985a089f09a65edd80b11cb75c767b57ba47391fee4c969f7215c96 - languageName: node - linkType: hard - -"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": - version: 10.4.3 - resolution: "lru-cache@npm:10.4.3" - checksum: 10c0/ebd04fbca961e6c1d6c0af3799adcc966a1babe798f685bb84e6599266599cd95d94630b10262f5424539bc4640107e8a33aa28585374abf561d30d16f4b39fb - languageName: node - linkType: hard - -"make-fetch-happen@npm:^14.0.3": - version: 14.0.3 - resolution: "make-fetch-happen@npm:14.0.3" - dependencies: - "@npmcli/agent": "npm:^3.0.0" - cacache: "npm:^19.0.1" - http-cache-semantics: "npm:^4.1.1" - minipass: "npm:^7.0.2" - minipass-fetch: "npm:^4.0.0" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.4" - negotiator: "npm:^1.0.0" - proc-log: "npm:^5.0.0" - promise-retry: "npm:^2.0.1" - ssri: "npm:^12.0.0" - checksum: 10c0/c40efb5e5296e7feb8e37155bde8eb70bc57d731b1f7d90e35a092fde403d7697c56fb49334d92d330d6f1ca29a98142036d6480a12681133a0a1453164cb2f0 - languageName: node - linkType: hard - -"minimatch@npm:^9.0.4": - version: 9.0.5 - resolution: "minimatch@npm:9.0.5" - dependencies: - brace-expansion: "npm:^2.0.1" - checksum: 10c0/de96cf5e35bdf0eab3e2c853522f98ffbe9a36c37797778d2665231ec1f20a9447a7e567cb640901f89e4daaa95ae5d70c65a9e8aa2bb0019b6facbc3c0575ed - languageName: node - linkType: hard - -"minipass-collect@npm:^2.0.1": - version: 2.0.1 - resolution: "minipass-collect@npm:2.0.1" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e - languageName: node - linkType: hard - -"minipass-fetch@npm:^4.0.0": - version: 4.0.1 - resolution: "minipass-fetch@npm:4.0.1" - dependencies: - encoding: "npm:^0.1.13" - minipass: "npm:^7.0.3" - minipass-sized: "npm:^1.0.3" - minizlib: "npm:^3.0.1" - dependenciesMeta: - encoding: - optional: true - checksum: 10c0/a3147b2efe8e078c9bf9d024a0059339c5a09c5b1dded6900a219c218cc8b1b78510b62dae556b507304af226b18c3f1aeb1d48660283602d5b6586c399eed5c - languageName: node - linkType: hard - -"minipass-flush@npm:^1.0.5": - version: 1.0.5 - resolution: "minipass-flush@npm:1.0.5" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/2a51b63feb799d2bb34669205eee7c0eaf9dce01883261a5b77410c9408aa447e478efd191b4de6fc1101e796ff5892f8443ef20d9544385819093dbb32d36bd - languageName: node - linkType: hard - -"minipass-pipeline@npm:^1.2.4": - version: 1.2.4 - resolution: "minipass-pipeline@npm:1.2.4" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2 - languageName: node - linkType: hard - -"minipass-sized@npm:^1.0.3": - version: 1.0.3 - resolution: "minipass-sized@npm:1.0.3" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb - languageName: node - linkType: hard - -"minipass@npm:^3.0.0": - version: 3.3.6 - resolution: "minipass@npm:3.3.6" - dependencies: - yallist: "npm:^4.0.0" - checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c - languageName: node - linkType: hard - -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": - version: 7.1.2 - resolution: "minipass@npm:7.1.2" - checksum: 10c0/b0fd20bb9fb56e5fa9a8bfac539e8915ae07430a619e4b86ff71f5fc757ef3924b23b2c4230393af1eda647ed3d75739e4e0acb250a6b1eb277cf7f8fe449557 - languageName: node - linkType: hard - -"minizlib@npm:^3.0.1": - version: 3.0.2 - resolution: "minizlib@npm:3.0.2" - dependencies: - minipass: "npm:^7.1.2" - checksum: 10c0/9f3bd35e41d40d02469cb30470c55ccc21cae0db40e08d1d0b1dff01cc8cc89a6f78e9c5d2b7c844e485ec0a8abc2238111213fdc5b2038e6d1012eacf316f78 - languageName: node - linkType: hard - -"mkdirp@npm:^3.0.1": - version: 3.0.1 - resolution: "mkdirp@npm:3.0.1" - bin: - mkdirp: dist/cjs/src/bin.js - checksum: 10c0/9f2b975e9246351f5e3a40dcfac99fcd0baa31fbfab615fe059fb11e51f10e4803c63de1f384c54d656e4db31d000e4767e9ef076a22e12a641357602e31d57d - languageName: node - linkType: hard - -"ms@npm:^2.1.3": - version: 2.1.3 - resolution: "ms@npm:2.1.3" - checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 - languageName: node - linkType: hard - -"negotiator@npm:^1.0.0": - version: 1.0.0 - resolution: "negotiator@npm:1.0.0" - checksum: 10c0/4c559dd52669ea48e1914f9d634227c561221dd54734070791f999c52ed0ff36e437b2e07d5c1f6e32909fc625fe46491c16e4a8f0572567d4dd15c3a4fda04b - languageName: node - linkType: hard - -"node-domexception@npm:^1.0.0": - version: 1.0.0 - resolution: "node-domexception@npm:1.0.0" - checksum: 10c0/5e5d63cda29856402df9472335af4bb13875e1927ad3be861dc5ebde38917aecbf9ae337923777af52a48c426b70148815e890a5d72760f1b4d758cc671b1a2b - languageName: node - linkType: hard - -"node-fetch@npm:^3.3.2": - version: 3.3.2 - resolution: "node-fetch@npm:3.3.2" - dependencies: - data-uri-to-buffer: "npm:^4.0.0" - fetch-blob: "npm:^3.1.4" - formdata-polyfill: "npm:^4.0.10" - checksum: 10c0/f3d5e56190562221398c9f5750198b34cf6113aa304e34ee97c94fd300ec578b25b2c2906edba922050fce983338fde0d5d34fcb0fc3336ade5bd0e429ad7538 - languageName: node - linkType: hard - -"node-gyp@npm:latest": - version: 11.2.0 - resolution: "node-gyp@npm:11.2.0" - dependencies: - env-paths: "npm:^2.2.0" - exponential-backoff: "npm:^3.1.1" - graceful-fs: "npm:^4.2.6" - make-fetch-happen: "npm:^14.0.3" - nopt: "npm:^8.0.0" - proc-log: "npm:^5.0.0" - semver: "npm:^7.3.5" - tar: "npm:^7.4.3" - tinyglobby: "npm:^0.2.12" - which: "npm:^5.0.0" - bin: - node-gyp: bin/node-gyp.js - checksum: 10c0/bd8d8c76b06be761239b0c8680f655f6a6e90b48e44d43415b11c16f7e8c15be346fba0cbf71588c7cdfb52c419d928a7d3db353afc1d952d19756237d8f10b9 - languageName: node - linkType: hard - -"nopt@npm:^8.0.0": - version: 8.1.0 - resolution: "nopt@npm:8.1.0" - dependencies: - abbrev: "npm:^3.0.0" - bin: - nopt: bin/nopt.js - checksum: 10c0/62e9ea70c7a3eb91d162d2c706b6606c041e4e7b547cbbb48f8b3695af457dd6479904d7ace600856bf923dd8d1ed0696f06195c8c20f02ac87c1da0e1d315ef - languageName: node - linkType: hard - -"p-map@npm:^7.0.2": - version: 7.0.3 - resolution: "p-map@npm:7.0.3" - checksum: 10c0/46091610da2b38ce47bcd1d8b4835a6fa4e832848a6682cf1652bc93915770f4617afc844c10a77d1b3e56d2472bb2d5622353fa3ead01a7f42b04fc8e744a5c - languageName: node - linkType: hard - -"package-json-from-dist@npm:^1.0.0": - version: 1.0.1 - resolution: "package-json-from-dist@npm:1.0.1" - checksum: 10c0/62ba2785eb655fec084a257af34dbe24292ab74516d6aecef97ef72d4897310bc6898f6c85b5cd22770eaa1ce60d55a0230e150fb6a966e3ecd6c511e23d164b - languageName: node - linkType: hard - -"path-key@npm:^3.1.0": - version: 3.1.1 - resolution: "path-key@npm:3.1.1" - checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c - languageName: node - linkType: hard - -"path-scurry@npm:^1.11.1": - version: 1.11.1 - resolution: "path-scurry@npm:1.11.1" - dependencies: - lru-cache: "npm:^10.2.0" - minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - checksum: 10c0/32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d - languageName: node - linkType: hard - -"picomatch@npm:^4.0.2": - version: 4.0.2 - resolution: "picomatch@npm:4.0.2" - checksum: 10c0/7c51f3ad2bb42c776f49ebf964c644958158be30d0a510efd5a395e8d49cb5acfed5b82c0c5b365523ce18e6ab85013c9ebe574f60305892ec3fa8eee8304ccc - languageName: node - linkType: hard - -"proc-log@npm:^5.0.0": - version: 5.0.0 - resolution: "proc-log@npm:5.0.0" - checksum: 10c0/bbe5edb944b0ad63387a1d5b1911ae93e05ce8d0f60de1035b218cdcceedfe39dbd2c697853355b70f1a090f8f58fe90da487c85216bf9671f9499d1a897e9e3 - languageName: node - linkType: hard - -"promise-retry@npm:^2.0.1": - version: 2.0.1 - resolution: "promise-retry@npm:2.0.1" - dependencies: - err-code: "npm:^2.0.2" - retry: "npm:^0.12.0" - checksum: 10c0/9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96 - languageName: node - linkType: hard - -"resolve-pkg-maps@npm:^1.0.0": - version: 1.0.0 - resolution: "resolve-pkg-maps@npm:1.0.0" - checksum: 10c0/fb8f7bbe2ca281a73b7ef423a1cbc786fb244bd7a95cbe5c3fba25b27d327150beca8ba02f622baea65919a57e061eb5005204daa5f93ed590d9b77463a567ab - languageName: node - linkType: hard - -"retry@npm:^0.12.0": - version: 0.12.0 - resolution: "retry@npm:0.12.0" - checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe - languageName: node - linkType: hard - -"safer-buffer@npm:>= 2.1.2 < 3.0.0": - version: 2.1.2 - resolution: "safer-buffer@npm:2.1.2" - checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 - languageName: node - linkType: hard - -"semver@npm:^7.3.5": - version: 7.7.2 - resolution: "semver@npm:7.7.2" - bin: - semver: bin/semver.js - checksum: 10c0/aca305edfbf2383c22571cb7714f48cadc7ac95371b4b52362fb8eeffdfbc0de0669368b82b2b15978f8848f01d7114da65697e56cd8c37b0dab8c58e543f9ea - languageName: node - linkType: hard - -"shebang-command@npm:^2.0.0": - version: 2.0.0 - resolution: "shebang-command@npm:2.0.0" - dependencies: - shebang-regex: "npm:^3.0.0" - checksum: 10c0/a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e - languageName: node - linkType: hard - -"shebang-regex@npm:^3.0.0": - version: 3.0.0 - resolution: "shebang-regex@npm:3.0.0" - checksum: 10c0/1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 - languageName: node - linkType: hard - -"signal-exit@npm:^4.0.1": - version: 4.1.0 - resolution: "signal-exit@npm:4.1.0" - checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 - languageName: node - linkType: hard - -"smart-buffer@npm:^4.2.0": - version: 4.2.0 - resolution: "smart-buffer@npm:4.2.0" - checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539 - languageName: node - linkType: hard - -"socks-proxy-agent@npm:^8.0.3": - version: 8.0.5 - resolution: "socks-proxy-agent@npm:8.0.5" - dependencies: - agent-base: "npm:^7.1.2" - debug: "npm:^4.3.4" - socks: "npm:^2.8.3" - checksum: 10c0/5d2c6cecba6821389aabf18728325730504bf9bb1d9e342e7987a5d13badd7a98838cc9a55b8ed3cb866ad37cc23e1086f09c4d72d93105ce9dfe76330e9d2a6 - languageName: node - linkType: hard - -"socks@npm:^2.8.3": - version: 2.8.4 - resolution: "socks@npm:2.8.4" - dependencies: - ip-address: "npm:^9.0.5" - smart-buffer: "npm:^4.2.0" - checksum: 10c0/00c3271e233ccf1fb83a3dd2060b94cc37817e0f797a93c560b9a7a86c4a0ec2961fb31263bdd24a3c28945e24868b5f063cd98744171d9e942c513454b50ae5 - languageName: node - linkType: hard - -"sprintf-js@npm:^1.1.3": - version: 1.1.3 - resolution: "sprintf-js@npm:1.1.3" - checksum: 10c0/09270dc4f30d479e666aee820eacd9e464215cdff53848b443964202bf4051490538e5dd1b42e1a65cf7296916ca17640aebf63dae9812749c7542ee5f288dec - languageName: node - linkType: hard - -"ssri@npm:^12.0.0": - version: 12.0.0 - resolution: "ssri@npm:12.0.0" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/caddd5f544b2006e88fa6b0124d8d7b28208b83c72d7672d5ade44d794525d23b540f3396108c4eb9280dcb7c01f0bef50682f5b4b2c34291f7c5e211fd1417d - languageName: node - linkType: hard - -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0": - version: 4.2.3 - resolution: "string-width@npm:4.2.3" - dependencies: - emoji-regex: "npm:^8.0.0" - is-fullwidth-code-point: "npm:^3.0.0" - strip-ansi: "npm:^6.0.1" - checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b - languageName: node - linkType: hard - -"string-width@npm:^5.0.1, string-width@npm:^5.1.2": - version: 5.1.2 - resolution: "string-width@npm:5.1.2" - dependencies: - eastasianwidth: "npm:^0.2.0" - emoji-regex: "npm:^9.2.2" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca - languageName: node - linkType: hard - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": - version: 6.0.1 - resolution: "strip-ansi@npm:6.0.1" - dependencies: - ansi-regex: "npm:^5.0.1" - checksum: 10c0/1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952 - languageName: node - linkType: hard - -"strip-ansi@npm:^7.0.1": - version: 7.1.0 - resolution: "strip-ansi@npm:7.1.0" - dependencies: - ansi-regex: "npm:^6.0.1" - checksum: 10c0/a198c3762e8832505328cbf9e8c8381de14a4fa50a4f9b2160138158ea88c0f5549fb50cb13c651c3088f47e63a108b34622ec18c0499b6c8c3a5ddf6b305ac4 - languageName: node - linkType: hard - -"system-test-route@workspace:.": - version: 0.0.0-use.local - resolution: "system-test-route@workspace:." - dependencies: - "@hono/node-server": "npm:^1.13.8" - "@hono/node-ws": "npm:^1.1.0" - "@rivet-gg/actor-core": "npm:^5.1.2" - "@types/deno": "npm:^2.2.0" - "@types/node": "npm:^22.13.9" - "@types/ws": "npm:^8.18.0" - hono: "npm:^4.6.17" - node-fetch: "npm:^3.3.2" - tsx: "npm:^4.7.0" - typescript: "npm:^5.3.3" - ws: "npm:^8.18.1" - languageName: unknown - linkType: soft - -"tar@npm:^7.4.3": - version: 7.4.3 - resolution: "tar@npm:7.4.3" - dependencies: - "@isaacs/fs-minipass": "npm:^4.0.0" - chownr: "npm:^3.0.0" - minipass: "npm:^7.1.2" - minizlib: "npm:^3.0.1" - mkdirp: "npm:^3.0.1" - yallist: "npm:^5.0.0" - checksum: 10c0/d4679609bb2a9b48eeaf84632b6d844128d2412b95b6de07d53d8ee8baf4ca0857c9331dfa510390a0727b550fd543d4d1a10995ad86cdf078423fbb8d99831d - languageName: node - linkType: hard - -"tinyglobby@npm:^0.2.12": - version: 0.2.14 - resolution: "tinyglobby@npm:0.2.14" - dependencies: - fdir: "npm:^6.4.4" - picomatch: "npm:^4.0.2" - checksum: 10c0/f789ed6c924287a9b7d3612056ed0cda67306cd2c80c249fd280cf1504742b12583a2089b61f4abbd24605f390809017240e250241f09938054c9b363e51c0a6 - languageName: node - linkType: hard - -"tsx@npm:^4.7.0": - version: 4.19.4 - resolution: "tsx@npm:4.19.4" - dependencies: - esbuild: "npm:~0.25.0" - fsevents: "npm:~2.3.3" - get-tsconfig: "npm:^4.7.5" - dependenciesMeta: - fsevents: - optional: true - bin: - tsx: dist/cli.mjs - checksum: 10c0/f7b8d44362343fbde1f2ecc9832d243a450e1168dd09702a545ebe5f699aa6912e45b431a54b885466db414cceda48e5067b36d182027c43b2c02a4f99d8721e - languageName: node - linkType: hard - -"typescript@npm:^5.3.3": - version: 5.8.3 - resolution: "typescript@npm:5.8.3" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10c0/5f8bb01196e542e64d44db3d16ee0e4063ce4f3e3966df6005f2588e86d91c03e1fb131c2581baf0fb65ee79669eea6e161cd448178986587e9f6844446dbb48 - languageName: node - linkType: hard - -"typescript@patch:typescript@npm%3A^5.3.3#optional!builtin": - version: 5.8.3 - resolution: "typescript@patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10c0/39117e346ff8ebd87ae1510b3a77d5d92dae5a89bde588c747d25da5c146603a99c8ee588c7ef80faaf123d89ed46f6dbd918d534d641083177d5fac38b8a1cb - languageName: node - linkType: hard - -"undici-types@npm:~6.21.0": - version: 6.21.0 - resolution: "undici-types@npm:6.21.0" - checksum: 10c0/c01ed51829b10aa72fc3ce64b747f8e74ae9b60eafa19a7b46ef624403508a54c526ffab06a14a26b3120d055e1104d7abe7c9017e83ced038ea5cf52f8d5e04 - languageName: node - linkType: hard - -"unique-filename@npm:^4.0.0": - version: 4.0.0 - resolution: "unique-filename@npm:4.0.0" - dependencies: - unique-slug: "npm:^5.0.0" - checksum: 10c0/38ae681cceb1408ea0587b6b01e29b00eee3c84baee1e41fd5c16b9ed443b80fba90c40e0ba69627e30855570a34ba8b06702d4a35035d4b5e198bf5a64c9ddc - languageName: node - linkType: hard - -"unique-slug@npm:^5.0.0": - version: 5.0.0 - resolution: "unique-slug@npm:5.0.0" - dependencies: - imurmurhash: "npm:^0.1.4" - checksum: 10c0/d324c5a44887bd7e105ce800fcf7533d43f29c48757ac410afd42975de82cc38ea2035c0483f4de82d186691bf3208ef35c644f73aa2b1b20b8e651be5afd293 - languageName: node - linkType: hard - -"web-streams-polyfill@npm:^3.0.3": - version: 3.3.3 - resolution: "web-streams-polyfill@npm:3.3.3" - checksum: 10c0/64e855c47f6c8330b5436147db1c75cb7e7474d924166800e8e2aab5eb6c76aac4981a84261dd2982b3e754490900b99791c80ae1407a9fa0dcff74f82ea3a7f - languageName: node - linkType: hard - -"which@npm:^2.0.1": - version: 2.0.2 - resolution: "which@npm:2.0.2" - dependencies: - isexe: "npm:^2.0.0" - bin: - node-which: ./bin/node-which - checksum: 10c0/66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f - languageName: node - linkType: hard - -"which@npm:^5.0.0": - version: 5.0.0 - resolution: "which@npm:5.0.0" - dependencies: - isexe: "npm:^3.1.1" - bin: - node-which: bin/which.js - checksum: 10c0/e556e4cd8b7dbf5df52408c9a9dd5ac6518c8c5267c8953f5b0564073c66ed5bf9503b14d876d0e9c7844d4db9725fb0dcf45d6e911e17e26ab363dc3965ae7b - languageName: node - linkType: hard - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version: 7.0.0 - resolution: "wrap-ansi@npm:7.0.0" - dependencies: - ansi-styles: "npm:^4.0.0" - string-width: "npm:^4.1.0" - strip-ansi: "npm:^6.0.0" - checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da - languageName: node - linkType: hard - -"wrap-ansi@npm:^8.1.0": - version: 8.1.0 - resolution: "wrap-ansi@npm:8.1.0" - dependencies: - ansi-styles: "npm:^6.1.0" - string-width: "npm:^5.0.1" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 - languageName: node - linkType: hard - -"ws@npm:^8.17.0, ws@npm:^8.18.1": - version: 8.18.2 - resolution: "ws@npm:8.18.2" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 10c0/4b50f67931b8c6943c893f59c524f0e4905bbd183016cfb0f2b8653aa7f28dad4e456b9d99d285bbb67cca4fedd9ce90dfdfaa82b898a11414ebd66ee99141e4 - languageName: node - linkType: hard - -"yallist@npm:^4.0.0": - version: 4.0.0 - resolution: "yallist@npm:4.0.0" - checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a - languageName: node - linkType: hard - -"yallist@npm:^5.0.0": - version: 5.0.0 - resolution: "yallist@npm:5.0.0" - checksum: 10c0/a499c81ce6d4a1d260d4ea0f6d49ab4da09681e32c3f0472dee16667ed69d01dae63a3b81745a24bd78476ec4fcf856114cb4896ace738e01da34b2c42235416 - languageName: node - linkType: hard - -"zod@npm:^3.24.1": - version: 3.25.50 - resolution: "zod@npm:3.25.50" - checksum: 10c0/88f8e73198ebe986b1640610e8abf9b3fde1db5de1d1dcfe21138b4712e6d9e875521a15538c70b5eb4c52712f8d6261794e0716ad57b213c3b328e1bc423986 - languageName: node - linkType: hard diff --git a/examples/websocket/README.md b/examples/websocket/README.md deleted file mode 100644 index 0d5207267d..0000000000 --- a/examples/websocket/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# WebSocket - -Simple WebSocket implementation. - -## Prerequisites - -- [Rivet CLI](https://rivet.gg/docs/setup) - -## Deploying - -```sh -rivet login -rivet deploy -``` - -## Testing - -```sh -rivet deno --populate-env run -A ws_test.ts -``` - diff --git a/examples/websocket/package.json b/examples/websocket/package.json deleted file mode 100644 index 5bb726bea5..0000000000 --- a/examples/websocket/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "example-system-test", - "version": "1.0.0", - "private": true, - "dependencies": { - "@rivet-gg/actor": "^5.1.2", - "hono": "^4.6.17" - } -} diff --git a/examples/websocket/rivet.json b/examples/websocket/rivet.json deleted file mode 100644 index c76efeb1b9..0000000000 --- a/examples/websocket/rivet.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "builds": { - "ws": { - "script": "ws.ts", - "tags": { - "foo": "bar" - } - } - } -} diff --git a/examples/websocket/tsconfig.json b/examples/websocket/tsconfig.json deleted file mode 100644 index afacad332e..0000000000 --- a/examples/websocket/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "compilerOptions": { - "target": "ESNext", - "module": "ESNext", - "moduleResolution": "bundler", - "types": ["node", "deno"], - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - "noEmit": true, - "isolatedModules": true - }, - "include": ["**/*.ts"] -} diff --git a/examples/websocket/ws.ts b/examples/websocket/ws.ts deleted file mode 100644 index 2391b3f05f..0000000000 --- a/examples/websocket/ws.ts +++ /dev/null @@ -1,60 +0,0 @@ -import type { ActorContext } from "@rivet-gg/actor-core"; -import { Hono } from "hono"; -import { upgradeWebSocket } from "hono/deno"; - -// Setup Hono app -const app = new Hono(); - -app.get("/health", (c) => { - return c.text("ok"); -}); - -app.get( - "/ws", - upgradeWebSocket((c) => { - return { - onOpen(_event, ws) { - ws.send( - JSON.stringify([ - "init", - { - forwardedFor: c.header("x-forwarded-for"), - }, - ]), - ); - }, - onMessage(event, ws) { - if (typeof event.data === "string") { - const [eventType, data] = JSON.parse( - event.data.slice(0, 2 ** 13), - ); - switch (eventType) { - case "ping": - ws.send(JSON.stringify(["pong", data])); - break; - default: - console.warn("unknown event", eventType); - break; - } - } - }, - }; - }), -); - -// Start server -export default { - async start(ctx: ActorContext) { - // Find port - const portEnv = Deno.env.get("PORT_HTTP"); - if (!portEnv) { - throw new Error("missing PORT_HTTP"); - } - const port = Number.parseInt(portEnv); - - // Start server - console.log(`Listening on port ${port}`); - const server = Deno.serve({ port }, app.fetch); - await server.finished; - }, -}; diff --git a/examples/websocket/ws_test.ts b/examples/websocket/ws_test.ts deleted file mode 100644 index ab9a8ebaf8..0000000000 --- a/examples/websocket/ws_test.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { RivetClient } from "@rivet-gg/api"; - -// Can be opt since they're not required for dev -const RIVET_ENDPOINT = Deno.env.get("RIVET_ENDPOINT"); -const RIVET_SERVICE_TOKEN = Deno.env.get("RIVET_SERVICE_TOKEN"); -const RIVET_PROJECT = Deno.env.get("RIVET_PROJECT"); -const RIVET_ENVIRONMENT = Deno.env.get("RIVET_ENVIRONMENT"); - -let region = Deno.env.get("REGION"); -if (!region || region.length === 0) { - region = undefined; -} - -const client = new RivetClient({ - environment: RIVET_ENDPOINT, - token: RIVET_SERVICE_TOKEN, -}); - -async function run() { - let actorId: string | undefined; - try { - console.log("Creating actor", { region }); - const { actor } = await client.actor.create({ - project: RIVET_PROJECT, - environment: RIVET_ENVIRONMENT, - body: { - region, - tags: { - name: "ws", - }, - buildTags: { name: "ws", current: "true" }, - network: { - ports: { - http: { - protocol: "https", - // internalPort: 80, - routing: { - guard: {}, - }, - }, - }, - }, - lifecycle: { - durable: false, - }, - }, - }); - actorId = actor.id; - - const port = actor.network.ports.http; - const actorOrigin = `${port.protocol}://${port.hostname}:${port.port}${port.path ?? ""}`; - console.log("Created actor at", actorOrigin); - - await new Promise((resolve, reject) => { - // Open a WebSocket to that endpoint - const ws = new WebSocket(`${actorOrigin}/ws`); - - ws.onmessage = (evt) => { - const [type, body] = JSON.parse(evt.data); - if (type === "init") { - console.log("Init event data:", body); - } else if (type === "pong") { - console.log("Pong"); - ws.close(); - resolve(undefined); - } else { - console.warn("unknown message type", type); - } - }; - - ws.onopen = () => { - console.log("Ping"); - ws.send(JSON.stringify(["ping", 123])); - }; - - ws.onclose = () => { - console.log("WebSocket connection closed"); - }; - - ws.onerror = (err) => { - console.error("WS error", err); - reject("ws error"); - }; - }); - } catch (error) { - console.error("Error:", error); - } finally { - if (actorId) { - console.log("Destroying", actorId); - await client.actor.destroy(actorId, { - project: RIVET_PROJECT, - environment: RIVET_ENVIRONMENT, - }); - } - } -} - -await run(); diff --git a/frontend/.env b/frontend/.env new file mode 100644 index 0000000000..04d5e84ed2 --- /dev/null +++ b/frontend/.env @@ -0,0 +1,11 @@ +VITE_APP_API_URL=http://localhost:43708/api +VITE_APP_ASSETS_URL=https://assets2.rivet.gg +VITE_APP_SENTRY_DSN="https://66a566505cfb4341732a3d350f2b87e2@o4504307129188352.ingest.sentry.io/4506435887366144" +VITE_APP_SENTRY_PROJECT_ID="4506435887366144" +# This is a public-facing token, safe to commit to repo +VITE_APP_POSTHOG_API_KEY=phc_6kfTNEAVw7rn1LA51cO3D69FefbKupSWFaM7OUgEpEo +VITE_APP_POSTHOG_HOST=https://ph.rivet.gg + +# Overridden in CI +SENTRY_AUTH_TOKEN= + diff --git a/frontend/apps/hub/.env b/frontend/apps/hub/.env deleted file mode 100644 index d32ffca04b..0000000000 --- a/frontend/apps/hub/.env +++ /dev/null @@ -1,12 +0,0 @@ -VITE_APP_API_URL=http://127.0.0.1:6420 -VITE_APP_ASSETS_URL=https://assets2.rivet.gg -VITE_APP_SENTRY_DSN="https://66a566505cfb4341732a3d350f2b87e2@o4504307129188352.ingest.sentry.io/4506435887366144" -VITE_APP_SENTRY_PROJECT_ID="4506435887366144" -# This is a public-facing token, safe to commit to repo -VITE_APP_POSTHOG_API_KEY=phc_6kfTNEAVw7rn1LA51cO3D69FefbKupSWFaM7OUgEpEo -VITE_APP_POSTHOG_HOST=https://ph.rivet.gg - -# Overridden in CI -VITE_APP_OUTERBASE_PROVIDER_TOKEN= -SENTRY_AUTH_TOKEN= - diff --git a/frontend/apps/hub/.force-update b/frontend/apps/hub/.force-update deleted file mode 100644 index 546a3fe34f..0000000000 --- a/frontend/apps/hub/.force-update +++ /dev/null @@ -1 +0,0 @@ -Fri Jul 11 06:08:38 PM PDT 2025 diff --git a/frontend/apps/hub/ARCHITECTURE.md b/frontend/apps/hub/ARCHITECTURE.md deleted file mode 100644 index 234b5b7ea6..0000000000 --- a/frontend/apps/hub/ARCHITECTURE.md +++ /dev/null @@ -1,153 +0,0 @@ -# Hub Architecture - -## Overview - -The Hub is a React/TypeScript dashboard application built with: -- **TanStack Router** - File-based routing -- **TanStack Query** - Server state management -- **Jotai** - Complex client state -- **React Context** - Global app state -- **Tailwind CSS** - Styling - -## Directory Structure - -``` -src/ -├── domains/ # Feature domains -│ └── {domain}/ -│ ├── components/ # Domain-specific components -│ ├── queries/ # Query options & mutations -│ ├── data/ # Context providers -│ └── forms/ # Form schemas -├── routes/ # Page components (file-based) -├── components/ # Shared UI components -├── queries/ # Global query setup -├── hooks/ # Custom React hooks -├── lib/ # Utilities -└── app.tsx # Root setup -``` - -## State Management - -### Server State (TanStack Query) -```typescript -// Query pattern: src/domains/{domain}/queries/query-options.ts -export const actorLogsQueryOptions = ({ projectNameId, environmentNameId, actorId }) => - queryOptions({ - queryKey: ["project", projectNameId, "environment", environmentNameId, "actor", actorId, "logs"], - queryFn: async ({ signal }) => rivetClient.actors.logs.get(...), - meta: { watch: true }, // Enable real-time updates - }); -``` - -### Client State (Jotai) -Used for complex, modular state (e.g., actor management): -```typescript -// Atoms for fine-grained reactivity -export const currentActorIdAtom = atom(undefined); -export const actorsAtom = atom([]); -``` - -### Global State (React Context) -```typescript -// Context for app-wide concerns -AuthContext // User authentication -ProjectContext // Current project -EnvironmentContext // Current environment -``` - -## Query Patterns - -### Standard Query -```typescript -const { data } = useQuery(projectQueryOptions(projectId)); -``` - -### Infinite Query -```typescript -const { data, fetchNextPage } = useInfiniteQuery( - projectActorsQueryOptions({ projectNameId, environmentNameId }) -); -``` - -### Mutations -```typescript -const mutation = useMutation({ - mutationFn: (data) => rivetClient.actors.destroy(data), - onSuccess: () => queryClient.invalidateQueries(...) -}); -``` - -### Real-time Updates -Queries with `watchIndex` parameter automatically refetch when server data changes: -```typescript -queryFn: ({ meta }) => api.call({ - watchIndex: getMetaWatchIndex(meta) -}) -``` - -## Key Conventions - -### Query Keys -Hierarchical structure matching API resources: -```typescript -["project", projectId, "environment", envId, "actor", actorId, "logs"] -``` - -### File Naming -- Query options: `query-options.ts` -- Mutations: `mutations.ts` -- Context: `{resource}-context.tsx` -- Components: `{feature}-{component}.tsx` - -### Import Aliases -```typescript -@/domains // Domain logic -@/components // Shared components -@/queries // Query utilities -@/hooks // Custom hooks -@/lib // Utilities -``` - -## API Integration - -- **rivetClient**: Main API client (`@rivet-gg/api-full`) -- **rivetEeClient**: Enterprise API (`@rivet-gg/api-ee`) -- Auto token refresh on expiration -- Request deduplication & caching - -## Example: Adding a New Feature - -1. **Create query options**: - ```typescript - // src/domains/project/queries/feature/query-options.ts - export const featureQueryOptions = (id: string) => queryOptions({ - queryKey: ["feature", id], - queryFn: () => rivetClient.feature.get(id), - }); - ``` - -2. **Create mutations**: - ```typescript - // src/domains/project/queries/feature/mutations.ts - export const useCreateFeatureMutation = () => useMutation({ - mutationFn: (data) => rivetClient.feature.create(data), - }); - ``` - -3. **Create route**: - ```typescript - // src/routes/.../feature.tsx - export const Route = createFileRoute('...')({ - component: FeaturePage, - }); - ``` - -4. **Use in component**: - ```typescript - function FeaturePage() { - const { data } = useQuery(featureQueryOptions(id)); - const mutation = useCreateFeatureMutation(); - // ... - } - ``` \ No newline at end of file diff --git a/frontend/apps/hub/README.md b/frontend/apps/hub/README.md deleted file mode 100644 index 79b12767b0..0000000000 --- a/frontend/apps/hub/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Rivet Hub - -[hub.rivet.gg](https://hub.rivet.gg) - -## Developing - -```bash -cd frontend/apps/hub -yarn install -yarn dlx turbo dev -``` - -Open [http://localhost:5080](http://localhost:5080) in your browser to view the website. - -## Configuring - -Create a file called `.env.local` to override properties. - -## License - -This site template is a commercial product and is licensed under the [Tailwind UI license](https://tailwindui.com/license). - diff --git a/frontend/apps/hub/index.html b/frontend/apps/hub/index.html deleted file mode 100644 index 2c36e759b2..0000000000 --- a/frontend/apps/hub/index.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - Rivet - - -
- - - - - diff --git a/frontend/apps/hub/package.json b/frontend/apps/hub/package.json deleted file mode 100644 index a01c192d13..0000000000 --- a/frontend/apps/hub/package.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "name": "@rivet-gg/hub", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "ts-check": "tsc --noEmit", - "build": "vite build --mode=production --base=/", - "build:embedded": "vite build --mode=production --base=/ui/", - "preview": "vite preview" - }, - "dependencies": { - "@date-fns/utc": "^1.2.0", - "@fortawesome/fontawesome-svg-core": "^6.5.2", - "@fortawesome/free-brands-svg-icons": "^6.5.2", - "@fortawesome/free-solid-svg-icons": "^6.5.2", - "@fortawesome/react-fontawesome": "^0.2.2", - "@hookform/resolvers": "^3.3.4", - "@rivet-gg/api-ee": "file:./vendor/rivet-gg-api-ee.tgz", - "@rivet-gg/api-full": "workspace:*", - "@rivet-gg/components": "workspace:*", - "@rivet-gg/icons": "workspace:*", - "@sentry/react": "^8.26.0", - "@tanstack/query-broadcast-client-experimental": "^5.56.2", - "@tanstack/query-sync-storage-persister": "^5.56.2", - "@tanstack/react-query": "^5.56.2", - "@tanstack/react-query-devtools": "^5.58.0", - "@tanstack/react-query-persist-client": "^5.56.2", - "@tanstack/react-router": "^1.114.25", - "@tanstack/react-table": "^8.21.2", - "@tanstack/router-devtools": "^1.114.25", - "@tanstack/router-plugin": "^1.114.25", - "@tanstack/zod-adapter": "^1.114.25", - "@types/bcryptjs": "^2.4.6", - "actor-core": "^0.6.2", - "bcryptjs": "^2.4.3", - "esast-util-from-js": "^2.0.1", - "file-saver": "^2.0.5", - "framer-motion": "^11.2.11", - "jotai": "^2.12.2", - "lodash": "^4.17.21", - "nanoid": "^5.1.5", - "posthog-js": "^1.144.2", - "react": "^19.0.0", - "react-dom": "^19.0.0", - "react-hook-form": "^7.51.1", - "react-inspector": "^6.0.2", - "react-konami-code": "^2.3.0", - "react-turnstile": "^1.1.3", - "recharts": "^2.12.7", - "strip-ansi": "^7.1.0", - "superjson": "^2.2.1", - "tailwind-merge": "^2.2.2", - "tailwindcss-animate": "^1.0.7", - "usehooks-ts": "^3.1.0", - "zod": "^3.24" - }, - "devDependencies": { - "@mdx-js/rollup": "^3.1.0", - "@sentry/vite-plugin": "^2.22.2", - "@shikijs/transformers": "^1.24.2", - "@types/file-saver": "^2", - "@types/filesize": "^5.0.2", - "@types/lodash": "^4.17.14", - "@types/mdx": "^2.0.13", - "@types/mime": "^4.0.0", - "@types/node": "^20.11.30", - "@types/react": "^18.2.66", - "@types/react-dom": "^18.2.22", - "@vitejs/plugin-react": "^4.2.1", - "autoprefixer": "^10.4.19", - "postcss": "^8.4.38", - "remark-gfm": "^4.0.1", - "rollup-plugin-visualizer": "^5.14.0", - "shiki": "^1.24.2", - "tailwindcss": "^3.4.1", - "turnstile-types": "^1.2.1", - "typescript": "^5.5.4", - "vite": "^5.2.0", - "vite-bundle-analyzer": "^0.17.0", - "vite-plugin-favicons-inject": "^2.2.0" - } -} diff --git a/frontend/apps/hub/public/greg.svg b/frontend/apps/hub/public/greg.svg deleted file mode 100644 index 588b3d476d..0000000000 --- a/frontend/apps/hub/public/greg.svg +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/apps/hub/public/icon-bordered.svg b/frontend/apps/hub/public/icon-bordered.svg deleted file mode 100644 index 81337354dd..0000000000 --- a/frontend/apps/hub/public/icon-bordered.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/frontend/apps/hub/public/icon-white-borderless.svg b/frontend/apps/hub/public/icon-white-borderless.svg deleted file mode 100644 index 9086ec836c..0000000000 --- a/frontend/apps/hub/public/icon-white-borderless.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/apps/hub/public/icon-white.svg b/frontend/apps/hub/public/icon-white.svg deleted file mode 100644 index 287c425791..0000000000 --- a/frontend/apps/hub/public/icon-white.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/apps/hub/public/icons/android-144x144.png b/frontend/apps/hub/public/icons/android-144x144.png deleted file mode 100644 index 7900d54635..0000000000 Binary files a/frontend/apps/hub/public/icons/android-144x144.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/android-192x192.png b/frontend/apps/hub/public/icons/android-192x192.png deleted file mode 100644 index c541811e15..0000000000 Binary files a/frontend/apps/hub/public/icons/android-192x192.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/android-36x36.png b/frontend/apps/hub/public/icons/android-36x36.png deleted file mode 100644 index 200700d838..0000000000 Binary files a/frontend/apps/hub/public/icons/android-36x36.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/android-48x48.png b/frontend/apps/hub/public/icons/android-48x48.png deleted file mode 100644 index 6569904394..0000000000 Binary files a/frontend/apps/hub/public/icons/android-48x48.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/android-72x72.png b/frontend/apps/hub/public/icons/android-72x72.png deleted file mode 100644 index 53d62bf01c..0000000000 Binary files a/frontend/apps/hub/public/icons/android-72x72.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/android-96x96.png b/frontend/apps/hub/public/icons/android-96x96.png deleted file mode 100644 index 93b12f09c1..0000000000 Binary files a/frontend/apps/hub/public/icons/android-96x96.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/android-chrome-192x192.png b/frontend/apps/hub/public/icons/android-chrome-192x192.png deleted file mode 100644 index c541811e15..0000000000 Binary files a/frontend/apps/hub/public/icons/android-chrome-192x192.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/android-chrome-512x512.png b/frontend/apps/hub/public/icons/android-chrome-512x512.png deleted file mode 100644 index 3102a0a424..0000000000 Binary files a/frontend/apps/hub/public/icons/android-chrome-512x512.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/android-chrome-maskable-192x192.png b/frontend/apps/hub/public/icons/android-chrome-maskable-192x192.png deleted file mode 100644 index c541811e15..0000000000 Binary files a/frontend/apps/hub/public/icons/android-chrome-maskable-192x192.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/android-chrome-maskable-512x512.png b/frontend/apps/hub/public/icons/android-chrome-maskable-512x512.png deleted file mode 100644 index 3102a0a424..0000000000 Binary files a/frontend/apps/hub/public/icons/android-chrome-maskable-512x512.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/apple-touch-icon.png b/frontend/apps/hub/public/icons/apple-touch-icon.png deleted file mode 100644 index ca016850f2..0000000000 Binary files a/frontend/apps/hub/public/icons/apple-touch-icon.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/browserconfig.xml b/frontend/apps/hub/public/icons/browserconfig.xml deleted file mode 100644 index 910d43d09f..0000000000 --- a/frontend/apps/hub/public/icons/browserconfig.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - #0c0a09 - - - diff --git a/frontend/apps/hub/public/icons/favicon-16x16.png b/frontend/apps/hub/public/icons/favicon-16x16.png deleted file mode 100644 index c34e97e412..0000000000 Binary files a/frontend/apps/hub/public/icons/favicon-16x16.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/favicon-32x32.png b/frontend/apps/hub/public/icons/favicon-32x32.png deleted file mode 100644 index 6274777b28..0000000000 Binary files a/frontend/apps/hub/public/icons/favicon-32x32.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/favicon.ico b/frontend/apps/hub/public/icons/favicon.ico deleted file mode 100644 index 65d616b1c4..0000000000 Binary files a/frontend/apps/hub/public/icons/favicon.ico and /dev/null differ diff --git a/frontend/apps/hub/public/icons/icon-128x128.png b/frontend/apps/hub/public/icons/icon-128x128.png deleted file mode 100644 index c14cceface..0000000000 Binary files a/frontend/apps/hub/public/icons/icon-128x128.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/icon-144x144.png b/frontend/apps/hub/public/icons/icon-144x144.png deleted file mode 100644 index 60c33b6715..0000000000 Binary files a/frontend/apps/hub/public/icons/icon-144x144.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/icon-152x152.png b/frontend/apps/hub/public/icons/icon-152x152.png deleted file mode 100644 index 54f5b3d894..0000000000 Binary files a/frontend/apps/hub/public/icons/icon-152x152.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/icon-192x192.png b/frontend/apps/hub/public/icons/icon-192x192.png deleted file mode 100644 index b13e2b16b6..0000000000 Binary files a/frontend/apps/hub/public/icons/icon-192x192.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/icon-384x384.png b/frontend/apps/hub/public/icons/icon-384x384.png deleted file mode 100644 index ba49959a81..0000000000 Binary files a/frontend/apps/hub/public/icons/icon-384x384.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/icon-48x48.png b/frontend/apps/hub/public/icons/icon-48x48.png deleted file mode 100644 index bd42510c0a..0000000000 Binary files a/frontend/apps/hub/public/icons/icon-48x48.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/icon-512x512.png b/frontend/apps/hub/public/icons/icon-512x512.png deleted file mode 100644 index 5a4e31641d..0000000000 Binary files a/frontend/apps/hub/public/icons/icon-512x512.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/icon-72x72.png b/frontend/apps/hub/public/icons/icon-72x72.png deleted file mode 100644 index 409ea574a8..0000000000 Binary files a/frontend/apps/hub/public/icons/icon-72x72.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/icon-96x96.png b/frontend/apps/hub/public/icons/icon-96x96.png deleted file mode 100644 index d936fbea4a..0000000000 Binary files a/frontend/apps/hub/public/icons/icon-96x96.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/msapplication-icon-144x144.png b/frontend/apps/hub/public/icons/msapplication-icon-144x144.png deleted file mode 100644 index 7900d54635..0000000000 Binary files a/frontend/apps/hub/public/icons/msapplication-icon-144x144.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/mstile-150x150.png b/frontend/apps/hub/public/icons/mstile-150x150.png deleted file mode 100644 index 6f177d85e1..0000000000 Binary files a/frontend/apps/hub/public/icons/mstile-150x150.png and /dev/null differ diff --git a/frontend/apps/hub/public/icons/safari-pinned-tab.svg b/frontend/apps/hub/public/icons/safari-pinned-tab.svg deleted file mode 100644 index a429a7ab5e..0000000000 --- a/frontend/apps/hub/public/icons/safari-pinned-tab.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - -Created by potrace 1.14, written by Peter Selinger 2001-2017 - - - - - diff --git a/frontend/apps/hub/public/icons/site.webmanifest b/frontend/apps/hub/public/icons/site.webmanifest deleted file mode 100644 index 99ebbacec6..0000000000 --- a/frontend/apps/hub/public/icons/site.webmanifest +++ /dev/null @@ -1,52 +0,0 @@ -{ - "name": "Rivet", - "short_name": "Rivet", - "icons": [ - { - "src": "assets/icons/icon-72x72.png", - "sizes": "72x72", - "type": "image/png" - }, - { - "src": "assets/icons/icon-96x96.png", - "sizes": "96x96", - "type": "image/png" - }, - { - "src": "assets/icons/icon-128x128.png", - "sizes": "128x128", - "type": "image/png" - }, - { - "src": "assets/icons/icon-144x144.png", - "sizes": "144x144", - "type": "image/png" - }, - { - "src": "assets/icons/icon-152x152.png", - "sizes": "152x152", - "type": "image/png" - }, - { - "src": "assets/icons/icon-192x192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "assets/icons/icon-384x384.png", - "sizes": "384x384", - "type": "image/png" - }, - { - "src": "assets/icons/icon-512x512.png", - "sizes": "512x512", - "type": "image/png" - } - ], - "theme_color": "#0c0a09", - "background_color": "#0c0a09", - "id": "/", - "start_url": "/", - "scope": "/", - "display": "standalone" -} diff --git a/frontend/apps/hub/src/app.tsx b/frontend/apps/hub/src/app.tsx deleted file mode 100644 index aadb4f7864..0000000000 --- a/frontend/apps/hub/src/app.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import { - ConfigProvider, - FullscreenLoading, - ThirdPartyProviders, - Toaster, - TooltipProvider, - getConfig, -} from "@rivet-gg/components"; -import { PageLayout } from "@rivet-gg/components/layout"; -import * as Sentry from "@sentry/react"; -import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; -import { PersistQueryClientProvider } from "@tanstack/react-query-persist-client"; -import { - CatchBoundary, - RouterProvider, - createRouter, -} from "@tanstack/react-router"; -import { Suspense } from "react"; -import { LayoutedErrorComponent } from "./components/error-component"; -import { AuthProvider, useAuth } from "./domains/auth/contexts/auth"; -import { routeMasks } from "./lib/route-masks"; -import { queryClient, queryClientPersister } from "./queries/global"; -import { routeTree } from "./routeTree.gen"; - -declare module "@tanstack/react-router" { - interface Register { - router: typeof router; - } - interface StaticDataRouteOption { - layout?: "full" | "compact" | "onboarding" | "actors" | "v2"; - } -} - -export const router = createRouter({ - basepath: import.meta.env.BASE_URL, - routeTree, - routeMasks, - context: { - // biome-ignore lint/style/noNonNullAssertion: we know this will be defined - auth: undefined!, - queryClient, - }, - // Since we're using React Query, we don't want loader calls to ever be stale - // This will ensure that the loader is always called when the route is preloaded or visited - - defaultPreload: "intent", - defaultPreloadStaleTime: 0, - defaultPendingComponent: PageLayout.Root.Skeleton, - defaultOnCatch: (error) => { - Sentry.captureException(error); - }, -}); - -function InnerApp() { - const auth = useAuth(); - return ; -} - -export function App({ cacheKey }: { cacheKey?: string }) { - return ( - - - - }> - - ""} - errorComponent={LayoutedErrorComponent} - > - - - - - - - - - - - - - ); -} diff --git a/frontend/apps/hub/src/components/auth-card.tsx b/frontend/apps/hub/src/components/auth-card.tsx deleted file mode 100644 index ba4e83d51d..0000000000 --- a/frontend/apps/hub/src/components/auth-card.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { Card } from "@rivet-gg/components"; -import type { ComponentProps } from "react"; - -export const AuthCard = (props: ComponentProps) => ( - // 18.75rem (300px, size of the cf widget) + 1.5rem (24px, padding) + 1.5rem (24px, padding) - -); diff --git a/frontend/apps/hub/src/components/breadcrumbs/breadcrumbs.tsx b/frontend/apps/hub/src/components/breadcrumbs/breadcrumbs.tsx deleted file mode 100644 index 736536803b..0000000000 --- a/frontend/apps/hub/src/components/breadcrumbs/breadcrumbs.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { useAuth } from "@/domains/auth/contexts/auth"; - -import { Skeleton, cn } from "@rivet-gg/components"; -import { ErrorBoundary } from "@sentry/react"; -import { useMatchRoute, useRouterState } from "@tanstack/react-router"; -import { Suspense, useContext } from "react"; -import { EnvironmentBreadcrumb } from "./environment-breadcrumb"; -import { GroupBreadcrumb } from "./group-breadcrumb"; -import { MobileBreadcrumbsContext } from "./mobile-breadcrumbs"; -import { ProjectBreadcrumb } from "./project-breadcrumb"; - -function Content() { - const matchRoute = useMatchRoute(); - - const { profile } = useAuth(); - if (!profile?.identity.isRegistered) { - return null; - } - - const groupMatch = matchRoute({ to: "/teams/$groupId", fuzzy: true }); - - if (groupMatch) { - return ; - } - - const projectEnvMatch = matchRoute({ - to: "/projects/$projectNameId/environments/$environmentNameId", - fuzzy: true, - }); - - if (projectEnvMatch) { - return ( - - ); - } - - const projectMatch = matchRoute({ - to: "/projects/$projectNameId", - fuzzy: true, - }); - - if (projectMatch) { - return ; - } - - return null; -} - -export function Breadcrumbs() { - const isMobile = useContext(MobileBreadcrumbsContext); - const pathname = useRouterState({ - select: (state) => state.location.pathname, - }); - return ( -
- { - console.log( - "Error occurred while rendering breadcrumbs.", - ...args, - ); - }} - > - - - - - - } - > - - - -
- ); -} diff --git a/frontend/apps/hub/src/components/breadcrumbs/environment-breadcrumb.tsx b/frontend/apps/hub/src/components/breadcrumbs/environment-breadcrumb.tsx deleted file mode 100644 index 6f5b6fb277..0000000000 --- a/frontend/apps/hub/src/components/breadcrumbs/environment-breadcrumb.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { EnvironmentSelect } from "@/domains/project/components/environment-select"; -import { - environmentByIdQueryOptions, - projectByIdQueryOptions, - projectQueryOptions, -} from "@/domains/project/queries"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { Link, useNavigate } from "@tanstack/react-router"; -import { useContext } from "react"; -import { Fragment } from "react/jsx-runtime"; -import { NavItem } from "../header/nav-item"; -import { MobileBreadcrumbsContext } from "./mobile-breadcrumbs"; -import { ProjectBreadcrumb } from "./project-breadcrumb"; -import { Separator } from "./separator"; - -interface EnvironmentBreadcrumbProps { - environmentNameId: string; - projectNameId: string; -} - -export function EnvironmentBreadcrumb({ - environmentNameId, - projectNameId, -}: EnvironmentBreadcrumbProps) { - const { - data: { gameId: projectId }, - } = useSuspenseQuery(projectByIdQueryOptions(projectNameId)); - - const { - data: { namespaceId: environmentId, displayName }, - } = useSuspenseQuery( - environmentByIdQueryOptions({ projectId, environmentNameId }), - ); - - const { - data: { namespaces: environments }, - } = useSuspenseQuery(projectQueryOptions(projectId)); - - const navigate = useNavigate(); - - const handleEnvironmentChange = (environmentId: string) => { - const environmentNameId = environments.find( - (env) => env.namespaceId === environmentId, - )?.nameId; - - if (!environmentNameId) return; - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId", - params: { projectNameId, environmentNameId }, - }); - }; - const isMobile = useContext(MobileBreadcrumbsContext); - - const Element = isMobile ? NavItem : Fragment; - - return ( - <> - - - - - {displayName} - - - navigate({ - to: ".", - search: { modal: "create-environment" }, - }) - } - showCreateEnvironment - onValueChange={handleEnvironmentChange} - /> - - - ); -} diff --git a/frontend/apps/hub/src/components/breadcrumbs/group-breadcrumb.tsx b/frontend/apps/hub/src/components/breadcrumbs/group-breadcrumb.tsx deleted file mode 100644 index 717cb4318f..0000000000 --- a/frontend/apps/hub/src/components/breadcrumbs/group-breadcrumb.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { GroupAvatar } from "@/domains/group/components/group-avatar"; -import { GroupSelect } from "@/domains/group/components/group-select"; -import { - groupProjectsQueryOptions, - groupsCountQueryOptions, -} from "@/domains/project/queries"; -import { useSuspenseQueries } from "@tanstack/react-query"; -import { Link, useNavigate } from "@tanstack/react-router"; -import { Fragment, useContext } from "react"; -import { NavItem } from "../header/nav-item"; -import { MobileBreadcrumbsContext } from "./mobile-breadcrumbs"; - -interface GroupBreadcrumbProps { - groupId: string; -} - -export function GroupBreadcrumb({ groupId }: GroupBreadcrumbProps) { - const [{ data: groupsCount }, { data }] = useSuspenseQueries({ - queries: [ - groupsCountQueryOptions(), - groupProjectsQueryOptions(groupId), - ], - }); - - const navigate = useNavigate(); - - const handleGroupChange = (groupId: string) => { - navigate({ - to: "/teams/$groupId", - params: { groupId }, - }); - }; - - const isMobile = useContext(MobileBreadcrumbsContext); - - const Element = isMobile ? NavItem : Fragment; - - if (!data) { - return null; - } - - return ( - - - - {data.displayName} - - {groupsCount > 1 ? ( - - navigate({ to: ".", search: { modal: "create-group" } }) - } - value={groupId} - onValueChange={handleGroupChange} - /> - ) : null} - - ); -} diff --git a/frontend/apps/hub/src/components/breadcrumbs/mobile-breadcrumbs.tsx b/frontend/apps/hub/src/components/breadcrumbs/mobile-breadcrumbs.tsx deleted file mode 100644 index 096bd6a749..0000000000 --- a/frontend/apps/hub/src/components/breadcrumbs/mobile-breadcrumbs.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { createContext } from "react"; -import { Breadcrumbs } from "./breadcrumbs"; - -export const MobileBreadcrumbsContext = createContext(false); - -export function MobileBreadcrumbs() { - return ( - - - - ); -} diff --git a/frontend/apps/hub/src/components/breadcrumbs/project-breadcrumb.tsx b/frontend/apps/hub/src/components/breadcrumbs/project-breadcrumb.tsx deleted file mode 100644 index 6a4b778fcc..0000000000 --- a/frontend/apps/hub/src/components/breadcrumbs/project-breadcrumb.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { GroupProjectSelect } from "@/domains/project/components/group-project-select"; -import { - projectByIdQueryOptions, - projectQueryOptions, - projectsQueryOptions, -} from "@/domains/project/queries"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { Link, useNavigate } from "@tanstack/react-router"; -import { Fragment, useContext } from "react"; -import { NavItem } from "../header/nav-item"; -import { GroupBreadcrumb } from "./group-breadcrumb"; -import { MobileBreadcrumbsContext } from "./mobile-breadcrumbs"; -import { Separator } from "./separator"; - -interface ProjectBreadcrumbProps { - projectNameId: string; -} - -export function ProjectBreadcrumb({ projectNameId }: ProjectBreadcrumbProps) { - const { - data: { gameId: projectId }, - } = useSuspenseQuery(projectByIdQueryOptions(projectNameId)); - const { data } = useSuspenseQuery(projectQueryOptions(projectId)); - const { data: projects } = useSuspenseQuery(projectsQueryOptions()); - - const navigate = useNavigate(); - const handleProjectChange = (projectId: string) => { - const projectNameId = projects.find( - (project) => project.gameId === projectId, - )?.nameId; - - if (!projectNameId) return; - - navigate({ - to: "/projects/$projectNameId", - params: { projectNameId }, - }); - }; - - const isMobile = useContext(MobileBreadcrumbsContext); - - const Element = isMobile ? NavItem : Fragment; - - return ( - <> - - - - - {data.displayName} - - {projects.length > 1 ? ( - - navigate({ - to: ".", - search: { - modal: "create-project", - groupId: data.developerGroupId, - }, - }) - } - groupId={data.developerGroupId} - value={projectId} - onValueChange={handleProjectChange} - /> - ) : null} - - - ); -} diff --git a/frontend/apps/hub/src/components/breadcrumbs/separator.tsx b/frontend/apps/hub/src/components/breadcrumbs/separator.tsx deleted file mode 100644 index 8465311d9d..0000000000 --- a/frontend/apps/hub/src/components/breadcrumbs/separator.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { Icon, faChevronRight } from "@rivet-gg/icons"; -import { useContext } from "react"; -import { MobileBreadcrumbsContext } from "./mobile-breadcrumbs"; - -export function Separator() { - const isMobile = useContext(MobileBreadcrumbsContext); - if (isMobile) return null; - return ( - - ); -} diff --git a/frontend/apps/hub/src/components/command-panel.tsx b/frontend/apps/hub/src/components/command-panel.tsx deleted file mode 100644 index ef0d383f72..0000000000 --- a/frontend/apps/hub/src/components/command-panel.tsx +++ /dev/null @@ -1,205 +0,0 @@ -import { - Button, - CommandDialog, - CommandEmpty, - CommandInput, - CommandList, - CommandLoading, - Kbd, - ShimmerLine, - cn, -} from "@rivet-gg/components"; -import { useIsFetching } from "@tanstack/react-query"; -import { useMatchRoute } from "@tanstack/react-router"; -import { - type KeyboardEventHandler, - Suspense, - startTransition, - useCallback, - useEffect, - useState, -} from "react"; -import { CommandPanelNavigationBreadcrumbs } from "./command-panel/command-panel-navigation-breadcrumbs"; -import { - CommandPanelNavigationProvider, - type CommandPanelPage, -} from "./command-panel/command-panel-navigation-provider"; -import { EnvironmentCommandPanelPage } from "./command-panel/command-panel-page/environment-command-panel-page"; -import { GroupCommandPanelPage } from "./command-panel/command-panel-page/group-command-panel-page"; -import { IndexCommandPanelPage } from "./command-panel/command-panel-page/index-command-panel-page"; -import { ProjectCommandPanelPage } from "./command-panel/command-panel-page/project-command-panel-page"; - -export function CommandPanel({ className }: { className?: string }) { - const [isOpen, setOpen] = useState(false); - - const [search, setSearch] = useState(""); - const [pages, setPages] = useState([]); - const page = pages[pages.length - 1]; - const matchRoute = useMatchRoute(); - - // biome-ignore lint/correctness/useExhaustiveDependencies: we do not want to run this effect on every change of match route - const open = useCallback(() => { - startTransition(() => { - const isTeam = matchRoute({ - to: "/teams/$groupId", - fuzzy: true, - }) as { groupId: string } | false; - - if (isTeam) { - setPages([ - { key: "group", params: { groupId: isTeam.groupId } }, - ]); - } - - const isProject = matchRoute({ - to: "/projects/$projectNameId", - fuzzy: true, - }); - if (isProject) { - setPages([ - { - key: "project", - params: { projectNameId: isProject.projectNameId }, - }, - ]); - } - - const isEnvironment = matchRoute({ - to: "/projects/$projectNameId/environments/$environmentNameId", - fuzzy: true, - }); - if (isEnvironment) { - setPages([ - { - key: "project", - params: { projectNameId: isEnvironment.projectNameId }, - }, - { - key: "environment", - params: { - projectNameId: isEnvironment.projectNameId, - environmentNameId: isEnvironment.environmentNameId, - }, - }, - ]); - } - - setOpen((open) => !open); - }); - }, []); - - // biome-ignore lint/correctness/useExhaustiveDependencies: we do not want to run this effect on every change of match route - useEffect(() => { - const down = (e: KeyboardEvent) => { - if (e.key === "k" && (e.metaKey || e.ctrlKey)) { - e.preventDefault(); - open(); - } - }; - document.addEventListener("keydown", down); - return () => document.removeEventListener("keydown", down); - }, []); - - const handlePageChange = useCallback((page: CommandPanelPage) => { - startTransition(() => { - setPages((pages) => [...pages, page]); - setSearch(""); - }); - }, []); - - const handleClose = useCallback(() => { - startTransition(() => { - setOpen(false); - setSearch(""); - setPages([]); - }); - }, []); - - const handleKeyDown: KeyboardEventHandler = useCallback( - (e) => { - // Escape goes to previous page - // Backspace goes to previous page when search is empty - if ( - (e.key === "Escape" || (e.key === "Backspace" && !search)) && - pages.length > 0 - ) { - e.preventDefault(); - setPages((pages) => pages.slice(0, -1)); - } - }, - [pages.length, search], - ); - - const isLoading = - useIsFetching({ - predicate: (query) => !query.queryKey.includes("watch"), - }) > 0; - - return ( - <> - - - - - - - Hang on…} - > - {isLoading ? ( - - ) : null} - No results found. - {!page ? : null} - {page?.key === "group" ? ( - - ) : null} - {page?.key === "project" ? ( - - ) : null} - {page?.key === "environment" ? ( - - ) : null} - - - - - - ); -} diff --git a/frontend/apps/hub/src/components/command-panel/command-panel-groups/all-groups-command-panel-group.tsx b/frontend/apps/hub/src/components/command-panel/command-panel-groups/all-groups-command-panel-group.tsx deleted file mode 100644 index d063fcff2a..0000000000 --- a/frontend/apps/hub/src/components/command-panel/command-panel-groups/all-groups-command-panel-group.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { GroupAvatar } from "@/domains/group/components/group-avatar"; -import { projectsByGroupQueryOptions } from "@/domains/project/queries"; -import { CommandGroup, CommandItem } from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { useCommandPanelNavigation } from "../command-panel-navigation-provider"; - -export function AllGroupsCommandGroup() { - const { data } = useSuspenseQuery(projectsByGroupQueryOptions()); - - const { changePage } = useCommandPanelNavigation(); - - return ( - - {data.map((group) => { - return ( - - changePage({ - key: "group", - params: { groupId: group.groupId }, - }) - } - > - - {group.displayName} - - ); - })} - - ); -} diff --git a/frontend/apps/hub/src/components/command-panel/command-panel-groups/all-projects-command-panel-group.tsx b/frontend/apps/hub/src/components/command-panel/command-panel-groups/all-projects-command-panel-group.tsx deleted file mode 100644 index 31eb6eb993..0000000000 --- a/frontend/apps/hub/src/components/command-panel/command-panel-groups/all-projects-command-panel-group.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { projectsByGroupQueryOptions } from "@/domains/project/queries"; -import { CommandGroup } from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { ProjectsCommandPanelItems } from "../projects-command-panel-items"; - -export function AllProjectsProjectsCommandGroup() { - const { data } = useSuspenseQuery(projectsByGroupQueryOptions()); - - return ( - - {data.map((group) => ( - - ))} - - ); -} diff --git a/frontend/apps/hub/src/components/command-panel/command-panel-groups/rivet-command-panel-group.tsx b/frontend/apps/hub/src/components/command-panel/command-panel-groups/rivet-command-panel-group.tsx deleted file mode 100644 index b475604eca..0000000000 --- a/frontend/apps/hub/src/components/command-panel/command-panel-groups/rivet-command-panel-group.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { CommandGroup, CommandItem } from "@rivet-gg/components"; -import { - Icon, - faBook, - faComment, - faLifeRing, - faMessageHeart, -} from "@rivet-gg/icons"; -import { useNavigate } from "@tanstack/react-router"; - -export function RivetCommandGroup() { - const navigate = useNavigate(); - return ( - - window.open("https://rivet.gg/docs", "_blank")} - > - - Docs - - - - navigate({ to: ".", search: { modal: "feedback" } }) - } - > - - Feedback - - - window.open("https://rivet.gg/support", "_blank") - } - > - - Support - - - window.open("https://rivet.gg/discord", "_blank") - } - > - - Discord - - - ); -} diff --git a/frontend/apps/hub/src/components/command-panel/command-panel-groups/suggestions-command-panel-group.tsx b/frontend/apps/hub/src/components/command-panel/command-panel-groups/suggestions-command-panel-group.tsx deleted file mode 100644 index f76ffce3de..0000000000 --- a/frontend/apps/hub/src/components/command-panel/command-panel-groups/suggestions-command-panel-group.tsx +++ /dev/null @@ -1,4 +0,0 @@ -export function SuggestionsCommandGroup() { - // This component is not implemented yet. - return null; -} diff --git a/frontend/apps/hub/src/components/command-panel/command-panel-navigation-breadcrumbs.tsx b/frontend/apps/hub/src/components/command-panel/command-panel-navigation-breadcrumbs.tsx deleted file mode 100644 index a459bc314b..0000000000 --- a/frontend/apps/hub/src/components/command-panel/command-panel-navigation-breadcrumbs.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import { GroupAvatar } from "@/domains/group/components/group-avatar"; -import { - environmentByIdQueryOptions, - groupProjectsQueryOptions, - projectByIdQueryOptions, - projectEnvironmentDisplayNameQueryOptions, - projectQueryOptions, -} from "@/domains/project/queries"; -import { Badge, Skeleton } from "@rivet-gg/components"; -import { Icon, faAngleRight, faPuzzle } from "@rivet-gg/icons"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { Fragment, Suspense } from "react"; -import type { CommandPanelPage } from "./command-panel-navigation-provider"; - -function GroupBreadcrumbs({ groupId }: { groupId: string }) { - const { data: group } = useSuspenseQuery( - groupProjectsQueryOptions(groupId), - ); - return ( - <> - - {group.displayName} - - ); -} - -function ProjectBreadcrumb({ projectNameId }: { projectNameId: string }) { - const { - data: { gameId: projectId }, - } = useSuspenseQuery(projectByIdQueryOptions(projectNameId)); - const { data: project } = useSuspenseQuery(projectQueryOptions(projectId)); - - return <>{project.displayName}; -} - -function EnvironmentBreadcrumb({ - projectNameId, - environmentNameId, -}: { - projectNameId: string; - environmentNameId: string; -}) { - const { - data: { gameId: projectId }, - } = useSuspenseQuery(projectByIdQueryOptions(projectNameId)); - - const { - data: { namespaceId: environmentId }, - } = useSuspenseQuery( - environmentByIdQueryOptions({ projectId, environmentNameId }), - ); - - const { data: environment } = useSuspenseQuery( - projectEnvironmentDisplayNameQueryOptions({ projectId, environmentId }), - ); - return {environment}; -} - -function BackendBreadcrumb() { - return ( - <> - Backend - - ); -} - -interface CommandPanelNavigationBreadcrumbsProps { - pages: CommandPanelPage[]; -} - -export function CommandPanelNavigationBreadcrumbs({ - pages, -}: CommandPanelNavigationBreadcrumbsProps) { - if (pages.length === 0) { - return null; - } - return ( -
- }> - {pages.map((page, index) => ( - - {index > 0 && ( - - )} - - {page.key === "group" && ( - - )} - {page.key === "project" && ( - - )} - {page.key === "environment" && ( - - )} - {page.key === "backend" && } - - - ))} - -
- ); -} diff --git a/frontend/apps/hub/src/components/command-panel/command-panel-navigation-provider.tsx b/frontend/apps/hub/src/components/command-panel/command-panel-navigation-provider.tsx deleted file mode 100644 index 56167f9a49..0000000000 --- a/frontend/apps/hub/src/components/command-panel/command-panel-navigation-provider.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import { type UseNavigateResult, useNavigate } from "@tanstack/react-router"; -import { - type ReactNode, - createContext, - startTransition, - useCallback, - useContext, -} from "react"; - -type GroupCommandPanelPage = { - key: "group"; - params: { groupId: string }; -}; - -type ProjectCommandPanelPage = { - key: "project"; - params: { projectNameId: string }; -}; - -type EnvironmentCommandPanelPage = { - key: "environment"; - params: { projectNameId: string; environmentNameId: string }; -}; - -type BackendCommandPanelPage = { - key: "backend"; - params: { projectNameId: string }; -}; - -type BackendEnvironmentPanelPage = { - key: "environment"; - params: { projectNameId: string; environmentNameId: string }; -}; - -type CommandPanelPages = - | GroupCommandPanelPage - | ProjectCommandPanelPage - | EnvironmentCommandPanelPage - | BackendCommandPanelPage - | BackendEnvironmentPanelPage - | never; - -export type CommandPanelPage = CommandPanelPages; - -const CommandPanelNavigationContext = createContext<{ - changePage: (page: CommandPanelPage) => void; - close: () => void; - navigate: UseNavigateResult; -}>({ - changePage: () => {}, - close: () => {}, - navigate: async () => {}, -}); - -export function CommandPanelNavigationProvider({ - children, - onClose, - onChangePage, - isLoading, -}: { - children: ReactNode; - onClose: () => void; - onChangePage: (page: CommandPanelPage) => void; - isLoading: boolean; -}) { - const routerNavigate = useNavigate(); - - const navigate: UseNavigateResult = useCallback( - async (params) => { - startTransition(() => { - onClose(); - routerNavigate(params); - }); - }, - [onClose, routerNavigate], - ); - - const handleChangePage = (page: CommandPanelPage) => { - if (isLoading) { - return; - } - onChangePage(page); - }; - - return ( - - {children} - - ); -} - -export const useCommandPanelNavigation = () => - useContext(CommandPanelNavigationContext); diff --git a/frontend/apps/hub/src/components/command-panel/command-panel-page/environment-command-panel-page.tsx b/frontend/apps/hub/src/components/command-panel/command-panel-page/environment-command-panel-page.tsx deleted file mode 100644 index cd23b8bd88..0000000000 --- a/frontend/apps/hub/src/components/command-panel/command-panel-page/environment-command-panel-page.tsx +++ /dev/null @@ -1,365 +0,0 @@ -import { - environmentByIdQueryOptions, - projectByIdQueryOptions, - projectEnvironmentQueryOptions, - projectMetadataQueryOptions, - projectQueryOptions, -} from "@/domains/project/queries"; -import { GuardEnterprise } from "@/lib/guards"; -import { - Badge, - CommandGroup, - CommandItem, - CommandSeparator, -} from "@rivet-gg/components"; -import { - Icon, - faActorsBorderless, - faBarsStaggered, - faCodeBranch, - faCog, - faFunction, - faGear, - faGlobe, - faJoystick, - faKey, - faLink, - faMagnifyingGlass, - faPuzzle, - faScroll, - faServer, - faUserCog, -} from "@rivet-gg/icons"; -import { useSuspenseQueries, useSuspenseQuery } from "@tanstack/react-query"; -import { useCommandPanelNavigation } from "../command-panel-navigation-provider"; - -interface EnvironmentCommandPanelPage { - projectNameId: string; - environmentNameId: string; -} - -export function EnvironmentCommandPanelPage({ - projectNameId, - environmentNameId, -}: EnvironmentCommandPanelPage) { - const { - data: { gameId: projectId }, - } = useSuspenseQuery(projectByIdQueryOptions(projectNameId)); - const { - data: { namespaceId: environmentId }, - } = useSuspenseQuery( - environmentByIdQueryOptions({ projectId, environmentNameId }), - ); - - const [ - { - data: { displayName, versions }, - }, - { - data: { legacyLobbiesEnabled, backendModulesEnabled }, - }, - ] = useSuspenseQueries({ - queries: [ - projectQueryOptions(projectId), - projectMetadataQueryOptions({ projectId, environmentId }), - ], - }); - - const { - data: { - namespace: { versionId, config }, - }, - } = useSuspenseQuery( - projectEnvironmentQueryOptions({ environmentId, projectId }), - ); - - const { navigate } = useCommandPanelNavigation(); - - const currentVersion = versions.find( - (version) => version.versionId === versionId, - ); - - return ( - <> - - { - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId/actors", - params: { projectNameId, environmentNameId }, - }); - }} - > - - Actors - - { - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId/containers", - params: { projectNameId, environmentNameId }, - }); - }} - > - - Containers - - { - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId/functions", - params: { projectNameId, environmentNameId }, - }); - }} - > - - Functions - - - { - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId/logs", - params: { projectNameId, environmentNameId }, - }); - }} - > - - Logs - - { - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId/actor-versions", - params: { projectNameId, environmentNameId }, - }); - }} - > - - Versions - - - { - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId/settings", - params: { projectNameId, environmentNameId }, - }); - }} - > - - Settings - - - { - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId/actors", - params: { projectNameId, environmentNameId }, - search: { modal: "go-to-actor" }, - }); - }} - > - - Go to Actor - - { - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId/containers", - params: { projectNameId, environmentNameId }, - search: { modal: "go-to-actor" }, - }); - }} - > - - Go to Container - - - {backendModulesEnabled ? ( - - { - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId/backend", - params: { - projectNameId, - environmentNameId, - }, - }); - }} - > - - Backend - - - ) : null} - - {legacyLobbiesEnabled ? ( - { - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId/versions", - params: { projectNameId, environmentNameId }, - }); - }} - > - - Versions - {currentVersion ? ( - - {currentVersion?.displayName} - - ) : null} - - ) : null} - - {legacyLobbiesEnabled ? ( - <> - {config.cdn ? ( - - { - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId/cdn", - params: { - projectNameId, - environmentNameId, - }, - }); - }} - > - - CDN Overview - - { - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId/cdn", - params: { - projectNameId, - environmentNameId, - }, - search: { modal: "cdn-users" }, - }); - }} - > - - Manage authenticated users - - { - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId/cdn", - params: { - projectNameId, - environmentNameId, - }, - search: { modal: "cdn-domains" }, - }); - }} - > - - Mange custom domains - - - ) : null} - {config.matchmaker ? ( - - { - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId/lobbies", - params: { - projectNameId, - environmentNameId, - }, - }); - }} - > - - Lobbies - - { - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId/lobbies/logs", - params: { - projectNameId, - environmentNameId, - }, - }); - }} - > - - Logs - - { - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId/lobbies/settings", - params: { - projectNameId, - environmentNameId, - }, - }); - }} - > - - Settings - - - ) : null} - - ) : null} - - {legacyLobbiesEnabled ? ( - { - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId/tokens", - params: { projectNameId, environmentNameId }, - search: { modal: "public-token" }, - }); - }} - > - - Generate a public token - - ) : null} - { - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId/tokens", - params: { projectNameId, environmentNameId }, - search: { modal: "service-token" }, - }); - }} - > - - Generate a service token - - {legacyLobbiesEnabled ? ( - { - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId/tokens", - params: { projectNameId, environmentNameId }, - }); - }} - > - - Generate a development token - - ) : null} - - - ); -} diff --git a/frontend/apps/hub/src/components/command-panel/command-panel-page/group-command-panel-page.tsx b/frontend/apps/hub/src/components/command-panel/command-panel-page/group-command-panel-page.tsx deleted file mode 100644 index da1f84cdec..0000000000 --- a/frontend/apps/hub/src/components/command-panel/command-panel-page/group-command-panel-page.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { groupProjectsQueryOptions } from "@/domains/project/queries"; -import { CommandGroup, CommandItem } from "@rivet-gg/components"; -import { - Icon, - faGear, - faHome, - faPlus, - faUserPlus, - faUsers, -} from "@rivet-gg/icons"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { useCommandPanelNavigation } from "../command-panel-navigation-provider"; -import { ProjectsCommandPanelItems } from "../projects-command-panel-items"; - -interface GroupCommandPanelPageProps { - groupId: string; -} - -export function GroupCommandPanelPage({ groupId }: GroupCommandPanelPageProps) { - const { data } = useSuspenseQuery(groupProjectsQueryOptions(groupId)); - - const { navigate } = useCommandPanelNavigation(); - return ( - <> - - { - navigate({ - to: "/teams/$groupId", - params: { groupId }, - }); - }} - > - - Overview - - { - navigate({ - to: "/teams/$groupId", - search: { modal: "invite" }, - params: { groupId }, - }); - }} - > - - Invite a member - - { - navigate({ - to: "/teams/$groupId/members", - params: { groupId }, - }); - }} - > - - Members - - { - navigate({ - to: "/teams/$groupId/settings", - params: { groupId }, - }); - }} - > - - Settings - - - - - { - navigate({ - to: "/teams/$groupId", - params: { groupId }, - search: { modal: "create-project" }, - }); - }} - > - - Create a new project - - - - - ); -} diff --git a/frontend/apps/hub/src/components/command-panel/command-panel-page/index-command-panel-page.tsx b/frontend/apps/hub/src/components/command-panel/command-panel-page/index-command-panel-page.tsx deleted file mode 100644 index ccf70212f1..0000000000 --- a/frontend/apps/hub/src/components/command-panel/command-panel-page/index-command-panel-page.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { useAuth } from "@/domains/auth/contexts/auth"; -import { AllGroupsCommandGroup } from "../command-panel-groups/all-groups-command-panel-group"; -import { AllProjectsProjectsCommandGroup } from "../command-panel-groups/all-projects-command-panel-group"; -import { RivetCommandGroup } from "../command-panel-groups/rivet-command-panel-group"; -import { SuggestionsCommandGroup } from "../command-panel-groups/suggestions-command-panel-group"; - -export function IndexCommandPanelPage() { - const auth = useAuth(); - return ( - <> - - - {auth.profile?.identity.isRegistered ? ( - <> - - - - ) : null} - - ); -} diff --git a/frontend/apps/hub/src/components/command-panel/command-panel-page/project-command-panel-page.tsx b/frontend/apps/hub/src/components/command-panel/command-panel-page/project-command-panel-page.tsx deleted file mode 100644 index 66bca5e6c3..0000000000 --- a/frontend/apps/hub/src/components/command-panel/command-panel-page/project-command-panel-page.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { - projectByIdQueryOptions, - projectQueryOptions, -} from "@/domains/project/queries"; -import { GuardEnterprise } from "@/lib/guards"; -import { CommandGroup, CommandItem } from "@rivet-gg/components"; -import { Icon, faCircleDollar, faCog, faHome, faKey } from "@rivet-gg/icons"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { useCommandPanelNavigation } from "../command-panel-navigation-provider"; -import { EnvironmentsCommandPanelItems } from "../environments-command-panel-items"; - -interface ProjectCommandPanelPage { - projectNameId: string; -} - -export function ProjectCommandPanelPage({ - projectNameId, -}: ProjectCommandPanelPage) { - const { data } = useSuspenseQuery(projectByIdQueryOptions(projectNameId)); - - const { data: project } = useSuspenseQuery( - projectQueryOptions(data.gameId), - ); - - const { navigate } = useCommandPanelNavigation(); - - return ( - <> - - { - navigate({ - to: "/projects/$projectNameId", - params: { projectNameId }, - }); - }} - > - - Overview - - - { - navigate({ - to: "/projects/$projectNameId/billing", - params: { projectNameId }, - }); - }} - > - - Billing - - - { - navigate({ - to: "/projects/$projectNameId/settings", - params: { projectNameId }, - }); - }} - > - - Settings - - - - - - - { - navigate({ - to: "/projects/$projectNameId", - params: { projectNameId }, - search: { modal: "cloud-token" }, - }); - }} - > - - Generate a cloud token - - - - ); -} diff --git a/frontend/apps/hub/src/components/command-panel/environments-command-panel-items.tsx b/frontend/apps/hub/src/components/command-panel/environments-command-panel-items.tsx deleted file mode 100644 index edcc66d052..0000000000 --- a/frontend/apps/hub/src/components/command-panel/environments-command-panel-items.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import type { Environment } from "@/domains/project/queries"; -import { Badge, CommandItem } from "@rivet-gg/components"; -import { useCommandPanelNavigation } from "./command-panel-navigation-provider"; - -interface EnvironmentsCommandPanelItemsProps { - namespaces: Environment[]; - projectNameId: string; -} - -export function EnvironmentsCommandPanelItems({ - namespaces, - projectNameId, -}: EnvironmentsCommandPanelItemsProps) { - const { changePage } = useCommandPanelNavigation(); - return ( - <> - {namespaces.map((environment) => ( - { - changePage({ - key: "environment", - params: { - projectNameId, - environmentNameId: environment.nameId, - }, - }); - }} - > - {environment.displayName}{" "} - {environment.version ? ( - - {environment.version?.displayName} - - ) : null} - - ))} - - ); -} diff --git a/frontend/apps/hub/src/components/command-panel/projects-command-panel-items.tsx b/frontend/apps/hub/src/components/command-panel/projects-command-panel-items.tsx deleted file mode 100644 index f1442026bb..0000000000 --- a/frontend/apps/hub/src/components/command-panel/projects-command-panel-items.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import type { Rivet } from "@rivet-gg/api-full"; -import { CommandItem } from "@rivet-gg/components"; -import { useCommandPanelNavigation } from "./command-panel-navigation-provider"; - -interface ProjectsCommandPanelItemsProps { - projects: Rivet.game.GameSummary[]; - groupId: string; -} - -export function ProjectsCommandPanelItems({ - projects, -}: ProjectsCommandPanelItemsProps) { - const { changePage } = useCommandPanelNavigation(); - return ( - <> - {projects.map((project) => ( - { - changePage({ - key: "project", - params: { projectNameId: project.nameId }, - }); - }} - > - {project.displayName} - - ))} - - ); -} diff --git a/frontend/apps/hub/src/components/dialogs/secret-dialog.tsx b/frontend/apps/hub/src/components/dialogs/secret-dialog.tsx deleted file mode 100644 index c365afc836..0000000000 --- a/frontend/apps/hub/src/components/dialogs/secret-dialog.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import type { DialogContentProps } from "@/hooks/use-dialog"; -import { publicUrl } from "@/lib/utils"; -import { - Code, - DialogHeader, - DialogTitle, - Flex, - Link, - Text, -} from "@rivet-gg/components"; - -interface ContentProps extends DialogContentProps {} - -export default function SecretDialogContent(props: ContentProps) { - return ( - <> - - Secret - - - Mysterious Rivet Frog - - Rivet 2.0 -
- {__APP_BUILD_ID__} -
- - - Ribbit! - - -
- - ); -} diff --git a/frontend/apps/hub/src/components/error-component.tsx b/frontend/apps/hub/src/components/error-component.tsx deleted file mode 100644 index 05cb8592d9..0000000000 --- a/frontend/apps/hub/src/components/error-component.tsx +++ /dev/null @@ -1,130 +0,0 @@ -import { ls } from "@/lib/ls"; -import { hasMethod, isRivetError } from "@/lib/utils"; -import { - Button, - Card, - CardContent, - CardFooter, - CardHeader, - CardTitle, - Code, - Text, -} from "@rivet-gg/components"; -import { PageLayout } from "@rivet-gg/components/layout"; -import { Icon, faBomb, faLock } from "@rivet-gg/icons"; -import * as Sentry from "@sentry/react"; -import { - useQueryClient, - useQueryErrorResetBoundary, -} from "@tanstack/react-query"; -import { - type ErrorComponentProps, - isNotFound, - useRouter, -} from "@tanstack/react-router"; -import posthog from "posthog-js"; -import { useEffect } from "react"; -import { NetworkIssueError } from "./network-issue-error"; -import { NotFoundComponent } from "./not-found-component"; - -export const ErrorComponent = ({ - error, - reset, -}: Partial) => { - const router = useRouter(); - const queryClient = useQueryClient(); - const queryErrorResetBoundary = useQueryErrorResetBoundary(); - - useEffect(() => { - if (isNotFound(error)) { - return; - } - console.dir(error); - posthog.capture("error", { error }, { send_instantly: true }); - if (error) { - Sentry.captureException(error); - posthog.captureException(error); - } - - // Reset the query error boundary - queryErrorResetBoundary.reset(); - }, [error, queryErrorResetBoundary]); - - if (isRivetError(error)) { - if ( - error.statusCode === 403 && - error.body.code === "GROUP_NOT_MEMBER" - ) { - return ( - - - - - Unauthorized - - - - You are not a member of this group. - - - - - - ); - } - if (error.statusCode === 404) { - return ; - } - } else if (!error) { - return ; - } else if ("statusCode" in error && "body" in error) { - return ; - } - - return ( - - - - - Uh, oh! - - - - Something went wrong! - - {hasMethod(error, "toString") - ? (error.toString() as string) - : JSON.stringify(error)} - - - - - - - ); -}; - -export function LayoutedErrorComponent(props: ErrorComponentProps) { - return ( - - - - ); -} diff --git a/frontend/apps/hub/src/components/header/changelog.tsx b/frontend/apps/hub/src/components/header/changelog.tsx deleted file mode 100644 index 9b6103b644..0000000000 --- a/frontend/apps/hub/src/components/header/changelog.tsx +++ /dev/null @@ -1,158 +0,0 @@ -import { changelogQueryOptions } from "@/domains/user/queries"; -import type { ChangelogItem } from "@/domains/user/queries/type"; -import { - Avatar, - AvatarFallback, - AvatarImage, - Badge, - Picture, - PictureFallback, - PictureImage, - Ping, - Skeleton, - WithTooltip, - cn, -} from "@rivet-gg/components"; -import { Icon, faSparkle } from "@rivet-gg/icons"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { useLocalStorage } from "usehooks-ts"; -import { NavItem } from "./nav-item"; - -interface ChangelogEntryProps extends ChangelogItem { - isNew?: boolean; -} - -export function ChangelogEntry({ - published, - images, - title, - description, - slug, - authors, - isNew, -}: ChangelogEntryProps) { - return ( -
-
-
-
- -
-

- {isNew ? ( - New Update - ) : ( - Latest Update - )} -

-
- - {new Date(published).toLocaleDateString()} - -
- - - - - - - - - -

{title}

- -

- {description}{" "} - - Read more... - -

-
- -
- ); -} -interface ChangelogProps { - className?: string; -} - -export function Changelog({ className }: ChangelogProps) { - const { data } = useSuspenseQuery(changelogQueryOptions()); - - const [lastChangelog, setLast] = useLocalStorage( - "rivet-lastchangelog", - null, - ); - - const hasNewChangelog = !lastChangelog - ? data.length > 0 - : data.some( - (entry) => new Date(entry.published) > new Date(lastChangelog), - ); - - const trigger = ( - - - {hasNewChangelog ? : null} - Changelog - - - ); - - return ( - { - if (isOpen) { - setLast(data[0].published); - } - }} - trigger={trigger} - content={} - /> - ); -} diff --git a/frontend/apps/hub/src/components/header/header-link.tsx b/frontend/apps/hub/src/components/header/header-link.tsx deleted file mode 100644 index 33ec599644..0000000000 --- a/frontend/apps/hub/src/components/header/header-link.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { Button, cn } from "@rivet-gg/components"; -import { Icon, type IconProp } from "@rivet-gg/icons"; -import { Link, type LinkProps, useMatchRoute } from "@tanstack/react-router"; -import { motion } from "framer-motion"; -import { type ReactNode, useContext } from "react"; -import { MobileBreadcrumbsContext } from "../breadcrumbs/mobile-breadcrumbs"; - -export interface HeaderLinkProps extends LinkProps { - icon?: IconProp; - className?: string; - children?: ReactNode; -} - -export function HeaderLink({ - icon, - children, - className, - ...props -}: HeaderLinkProps) { - const isMobile = useContext(MobileBreadcrumbsContext); - - const match = useMatchRoute(); - - // does not support function children (bug?) - const isCurrent = match({ to: props.to, ...props }); - - return ( - - ); -} diff --git a/frontend/apps/hub/src/components/header/header-route-loader.tsx b/frontend/apps/hub/src/components/header/header-route-loader.tsx deleted file mode 100644 index 57016fa852..0000000000 --- a/frontend/apps/hub/src/components/header/header-route-loader.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { ShimmerLine } from "@rivet-gg/components"; -import { useRouterState } from "@tanstack/react-router"; - -export function HeaderRouteLoader() { - const isLoading = useRouterState({ - select: (s) => s.isLoading || s.isTransitioning, - }); - - if (!isLoading) { - return null; - } - return ; -} diff --git a/frontend/apps/hub/src/components/header/header-sub-nav.tsx b/frontend/apps/hub/src/components/header/header-sub-nav.tsx deleted file mode 100644 index 13b5b178c2..0000000000 --- a/frontend/apps/hub/src/components/header/header-sub-nav.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import { useAuth } from "@/domains/auth/contexts/auth"; -import { Skeleton, cn } from "@rivet-gg/components"; -import { ErrorBoundary } from "@sentry/react"; -import { useMatchRoute, useMatches } from "@tanstack/react-router"; -import { Suspense, useContext } from "react"; -import { MobileBreadcrumbsContext } from "../breadcrumbs/mobile-breadcrumbs"; -import { HeaderEnvironmentLinks } from "./links/header-environment-links"; -import { HeaderGroupLinks } from "./links/header-group-links"; -import { HeaderProjectLinks } from "./links/header-project-links"; - -function Content() { - const allMatches = useMatches(); - - const v2Envs = allMatches.find((match) => match.id.includes("/_v2/")); - - const matchRoute = useMatchRoute(); - - const { profile } = useAuth(); - - if (!profile?.identity.isRegistered || v2Envs) { - return null; - } - - const namespaceMatch = matchRoute({ - to: "/projects/$projectNameId/environments/$environmentNameId", - fuzzy: true, - pending: false, - }); - - if (namespaceMatch) { - return ( - - ); - } - - const projectMatch = matchRoute({ - to: "/projects/$projectNameId", - fuzzy: true, - pending: false, - }); - - if (projectMatch) { - return ( - - ); - } - - const groupMatch = matchRoute({ - to: "/teams/$groupId", - fuzzy: true, - pending: false, - }); - - if (groupMatch) { - return ; - } - - return null; -} - -export function HeaderSubNav() { - const isMobile = useContext(MobileBreadcrumbsContext); - - return ( - - - - - - - } - > - - - - ); -} diff --git a/frontend/apps/hub/src/components/header/header.tsx b/frontend/apps/hub/src/components/header/header.tsx deleted file mode 100644 index 03489378ec..0000000000 --- a/frontend/apps/hub/src/components/header/header.tsx +++ /dev/null @@ -1,193 +0,0 @@ -import { useAuth } from "@/domains/auth/contexts/auth"; -import { publicUrl } from "@/lib/utils"; -import { - Button, - Flex, - Sheet, - SheetContent, - SheetTrigger, - cn, -} from "@rivet-gg/components"; -import { Icon, faBars } from "@rivet-gg/icons"; -import { ErrorBoundary } from "@sentry/react"; -import { Link } from "@tanstack/react-router"; -import { Breadcrumbs } from "../breadcrumbs/breadcrumbs"; -import { MobileBreadcrumbs } from "../breadcrumbs/mobile-breadcrumbs"; -import { CommandPanel } from "../command-panel"; -import { Changelog } from "./changelog"; -import { HeaderRouteLoader } from "./header-route-loader"; -import { HeaderSubNav } from "./header-sub-nav"; -import { MobileHeaderSubNav } from "./mobile-header-sub-nav"; -import { NavItem } from "./nav-item"; - -const UserProfileButton = () => { - const { profile } = useAuth(); - if (!profile?.identity.isRegistered) { - return null; - } - return ( - - ); -}; - -interface HeaderProps { - variant: "default" | "opaque"; -} - -export function Header({ variant = "opaque" }: HeaderProps) { - return ( -
- -
-
- - - - - - - - - -
- - - ({ - ...old, - modal: "feedback", - })} - > - Feedback - - - - - Changelog - - - } - > - - - - - Docs - - - -
-
- -
-
- ); -} diff --git a/frontend/apps/hub/src/components/header/links/header-environment-links.tsx b/frontend/apps/hub/src/components/header/links/header-environment-links.tsx deleted file mode 100644 index 248fa6870f..0000000000 --- a/frontend/apps/hub/src/components/header/links/header-environment-links.tsx +++ /dev/null @@ -1,116 +0,0 @@ -import { - environmentByIdQueryOptions, - projectByIdQueryOptions, - projectEnvironmentQueryOptions, - projectMetadataQueryOptions, -} from "@/domains/project/queries"; -import { GuardEnterprise } from "@/lib/guards"; -import { - faActorsBorderless, - faChessKnight, - faCodeBranch, - faGlobe, - faHammer, - faKey, - faPuzzle, -} from "@rivet-gg/icons"; -import { useSuspenseQueries, useSuspenseQuery } from "@tanstack/react-query"; -import { HeaderLink } from "../header-link"; - -interface EnvironmentLinksProps { - projectNameId: string; - environmentNameId: string; -} - -export function HeaderEnvironmentLinks({ - projectNameId, - environmentNameId, -}: EnvironmentLinksProps) { - const { - data: { gameId: projectId }, - } = useSuspenseQuery(projectByIdQueryOptions(projectNameId)); - - const { - data: { namespaceId: environmentId }, - } = useSuspenseQuery( - environmentByIdQueryOptions({ projectId, environmentNameId }), - ); - - const [ - { data }, - { - data: { legacyLobbiesEnabled, backendModulesEnabled }, - }, - ] = useSuspenseQueries({ - queries: [ - projectEnvironmentQueryOptions({ projectId, environmentId }), - projectMetadataQueryOptions({ projectId, environmentId }), - ], - }); - - return ( - <> - - Actors - - - Builds - - {backendModulesEnabled ? ( - - - Backend - - - ) : null} - {legacyLobbiesEnabled ? ( - <> - - Versions - - {data.namespace.config.matchmaker ? ( - - Lobbies - - ) : null} - {data.namespace.config.cdn ? ( - - CDN - - ) : null} - - ) : null} - - Tokens - - - ); -} diff --git a/frontend/apps/hub/src/components/header/links/header-group-links.tsx b/frontend/apps/hub/src/components/header/links/header-group-links.tsx deleted file mode 100644 index 68a52b92fc..0000000000 --- a/frontend/apps/hub/src/components/header/links/header-group-links.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { groupProjectsQueryOptions } from "@/domains/project/queries"; -import { faGear, faHome, faUsers } from "@rivet-gg/icons"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { HeaderLink } from "../header-link"; - -interface HeaderLinksLinkProps { - groupId: string; -} - -export function HeaderGroupLinks({ groupId }: HeaderLinksLinkProps) { - useSuspenseQuery(groupProjectsQueryOptions(groupId)); - return ( - <> - - Overview - - - Members - - - Settings - - - ); -} diff --git a/frontend/apps/hub/src/components/header/links/header-project-links.tsx b/frontend/apps/hub/src/components/header/links/header-project-links.tsx deleted file mode 100644 index fcf67dbb00..0000000000 --- a/frontend/apps/hub/src/components/header/links/header-project-links.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { GuardEnterprise } from "@/lib/guards"; -import { faCircleDollar, faFolder, faGear } from "@rivet-gg/icons"; -import { HeaderLink } from "../header-link"; - -interface HeaderProjectLinksProps { - projectNameId: string; -} - -export function HeaderProjectLinks({ projectNameId }: HeaderProjectLinksProps) { - return ( - <> - - Environments - - - - Billing - - - - Settings - - - ); -} diff --git a/frontend/apps/hub/src/components/header/mobile-header-sub-nav.tsx b/frontend/apps/hub/src/components/header/mobile-header-sub-nav.tsx deleted file mode 100644 index fd02247330..0000000000 --- a/frontend/apps/hub/src/components/header/mobile-header-sub-nav.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { MobileBreadcrumbsContext } from "../breadcrumbs/mobile-breadcrumbs"; -import { HeaderSubNav } from "./header-sub-nav"; - -export function MobileHeaderSubNav() { - return ( - - - - ); -} diff --git a/frontend/apps/hub/src/components/header/nav-item.tsx b/frontend/apps/hub/src/components/header/nav-item.tsx deleted file mode 100644 index 46cc3a1c25..0000000000 --- a/frontend/apps/hub/src/components/header/nav-item.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { Slot } from "@radix-ui/react-slot"; -import { cn } from "@rivet-gg/components"; -import { type PropsWithChildren, forwardRef } from "react"; - -interface NavItemProps extends PropsWithChildren { - asChild?: boolean; -} - -export const NavItem = forwardRef( - ({ className, asChild, ...props }, ref) => { - const Comp = asChild ? Slot : "a"; - return ( - - ); - }, -); diff --git a/frontend/apps/hub/src/components/intro.tsx b/frontend/apps/hub/src/components/intro.tsx deleted file mode 100644 index 980f54c1ac..0000000000 --- a/frontend/apps/hub/src/components/intro.tsx +++ /dev/null @@ -1,176 +0,0 @@ -import * as GroupCreateForm from "@/domains/group/forms/group-create-form"; -import { useGroupCreateMutation } from "@/domains/group/queries"; -import * as GroupCreateProjectForm from "@/domains/project/forms/group-create-project-form"; -import { - projectsByGroupQueryOptions, - projectsQueryOptions, - useProjectCreateMutation, -} from "@/domains/project/queries"; -import { queryClient } from "@/queries/global"; -import type { Rivet } from "@rivet-gg/api-full"; -import { - Card, - CardContent, - CardDescription, - CardHeader, - CardTitle, -} from "@rivet-gg/components"; -import * as Sentry from "@sentry/react"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { motion } from "framer-motion"; -import { useState } from "react"; - -enum Step { - CreateGroup = 0, - CreateProject = 1, -} - -interface IntroProps { - initialStep?: Step; - initialProjectName?: string; - onFinish?: (project: Rivet.game.GameSummary) => Promise | void; -} - -export function Intro({ - initialStep, - initialProjectName, - onFinish, -}: IntroProps) { - const { mutateAsync, data: createdGroupResponse } = - useGroupCreateMutation(); - const { mutateAsync: createProject, data: projectCreationData } = - useProjectCreateMutation(); - - const { data } = useSuspenseQuery(projectsByGroupQueryOptions()); - - const project = - data - .flatMap((team) => team.projects) - .find( - (project) => project.gameId === projectCreationData?.gameId, - ) || data.find((team) => team.projects.length > 0)?.projects[0]; - - const [step, setStep] = useState( - () => initialStep ?? (!project ? Step.CreateGroup : Step.CreateProject), - ); - - const groupId = createdGroupResponse?.groupId || project?.developer.groupId; - - if (step === Step.CreateProject) { - return ( - - - - { - const { gameId } = await createProject({ - displayName: values.name, - nameId: values.slug, - developerGroupId: - createdGroupResponse?.groupId || - data[0].groupId, - }); - - const { games } = await queryClient.fetchQuery( - projectsQueryOptions(), - ); - - const project = games.find( - (game) => game.gameId === gameId, - ); - - if (!project) { - Sentry.captureMessage( - "Project not found after creation", - "fatal", - ); - return; - } - - return onFinish?.(project); - }} - > - - Create Project - - You've created a team! Now you can create - projects and invite teammates. - - - -
- {initialProjectName ? ( - - ) : null} - - - - Create - -
-
-
-
-
-
- ); - } - - return ( - - - - { - await mutateAsync({ - displayName: values.name, - }); - setStep(Step.CreateProject); - }} - defaultValues={{ name: "" }} - > - - Create Team - - Before you start, you need to create a team. - This will allow you to create projects and - invite teammates. - - - -
- - - Create - -
-
-
-
-
-
- ); -} diff --git a/frontend/apps/hub/src/components/network-issue-error.tsx b/frontend/apps/hub/src/components/network-issue-error.tsx deleted file mode 100644 index 8e66a07bd5..0000000000 --- a/frontend/apps/hub/src/components/network-issue-error.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { - Button, - Card, - CardContent, - CardFooter, - CardHeader, - CardTitle, - Text, -} from "@rivet-gg/components"; -import { Icon, faWifiSlash } from "@rivet-gg/icons"; - -export const NetworkIssueError = () => { - return ( - - - - - Connection issue! - - - - - It seems that you do not have working network connection, or - one of your extension blocks hub from accessing required - resources. -
- Check your network connection, disable browser extensions - and try again. If the issue still persist, please contact - us. -
-
- - - -
- ); -}; diff --git a/frontend/apps/hub/src/components/not-found-component.tsx b/frontend/apps/hub/src/components/not-found-component.tsx deleted file mode 100644 index 8c4105a64a..0000000000 --- a/frontend/apps/hub/src/components/not-found-component.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { ls } from "@/lib/ls"; -import { - Button, - Card, - CardContent, - CardFooter, - CardHeader, - CardTitle, - Text, -} from "@rivet-gg/components"; -import { Icon, faFlagCheckered } from "@rivet-gg/icons"; -import { useQueryClient } from "@tanstack/react-query"; -import { useRouter } from "@tanstack/react-router"; - -export const NotFoundComponent = () => { - const router = useRouter(); - const queryClient = useQueryClient(); - - return ( - - - - - Wrong direction! - - - - This page does not exists! - - - - - - ); -}; diff --git a/frontend/apps/hub/src/components/onboarding-background.tsx b/frontend/apps/hub/src/components/onboarding-background.tsx deleted file mode 100644 index a55d0e35b1..0000000000 --- a/frontend/apps/hub/src/components/onboarding-background.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { usePageLayout } from "@/lib/compute-page-layout"; -import { useRouterState } from "@tanstack/react-router"; -import { motion } from "framer-motion"; -import { useState } from "react"; - -export function OnboardingBackground() { - const layout = usePageLayout(); - const [isLoaded, setIsLoaded] = useState(false); - const isRouteLoaded = useRouterState({ - select(state) { - return state.loadedAt; - }, - }); - - if (layout !== "onboarding") { - return null; - } - - return ( - { - setIsLoaded(true); - }} - muted - loop - className="fixed top-0 left-0 w-full h-full object-cover object-center" - > - - - ); -} diff --git a/frontend/apps/hub/src/components/onboarding/initial-setup-install-rivet-cli-cmd.sh b/frontend/apps/hub/src/components/onboarding/initial-setup-install-rivet-cli-cmd.sh deleted file mode 100644 index 5e3ba32e22..0000000000 --- a/frontend/apps/hub/src/components/onboarding/initial-setup-install-rivet-cli-cmd.sh +++ /dev/null @@ -1 +0,0 @@ -powershell -Command "iwr https://releases.rivet.gg/rivet/latest/install.ps1 -useb | iex" \ No newline at end of file diff --git a/frontend/apps/hub/src/components/onboarding/initial-setup-install-rivet-cli-powershell.sh b/frontend/apps/hub/src/components/onboarding/initial-setup-install-rivet-cli-powershell.sh deleted file mode 100644 index 10910f5a11..0000000000 --- a/frontend/apps/hub/src/components/onboarding/initial-setup-install-rivet-cli-powershell.sh +++ /dev/null @@ -1 +0,0 @@ -iwr https://releases.rivet.gg/rivet/latest/install.ps1 -useb | iex \ No newline at end of file diff --git a/frontend/apps/hub/src/components/onboarding/initial-setup-install-rivet-cli-source.sh b/frontend/apps/hub/src/components/onboarding/initial-setup-install-rivet-cli-source.sh deleted file mode 100644 index fa6ff9d995..0000000000 --- a/frontend/apps/hub/src/components/onboarding/initial-setup-install-rivet-cli-source.sh +++ /dev/null @@ -1,2 +0,0 @@ -git clone https://github.com/rivet-gg/rivet -cargo build --bin rivet diff --git a/frontend/apps/hub/src/components/onboarding/initial-setup-install-rivet-cli-unix.sh b/frontend/apps/hub/src/components/onboarding/initial-setup-install-rivet-cli-unix.sh deleted file mode 100644 index 12a43a3611..0000000000 --- a/frontend/apps/hub/src/components/onboarding/initial-setup-install-rivet-cli-unix.sh +++ /dev/null @@ -1 +0,0 @@ -curl -fsSL https://releases.rivet.gg/rivet/latest/install.sh | sh \ No newline at end of file diff --git a/frontend/apps/hub/src/components/onboarding/initial-setup-setup-rivet-cli.sh b/frontend/apps/hub/src/components/onboarding/initial-setup-setup-rivet-cli.sh deleted file mode 100644 index 5e5725b729..0000000000 --- a/frontend/apps/hub/src/components/onboarding/initial-setup-setup-rivet-cli.sh +++ /dev/null @@ -1,2 +0,0 @@ -rivet init -rivet deploy \ No newline at end of file diff --git a/frontend/apps/hub/src/components/onboarding/initial-setup-test-rivet-cli.sh b/frontend/apps/hub/src/components/onboarding/initial-setup-test-rivet-cli.sh deleted file mode 100644 index a352295db8..0000000000 --- a/frontend/apps/hub/src/components/onboarding/initial-setup-test-rivet-cli.sh +++ /dev/null @@ -1 +0,0 @@ -rivet deno run -A counter_test.ts \ No newline at end of file diff --git a/frontend/apps/hub/src/components/onboarding/install-cli.tsx b/frontend/apps/hub/src/components/onboarding/install-cli.tsx deleted file mode 100644 index 1b74dabe63..0000000000 --- a/frontend/apps/hub/src/components/onboarding/install-cli.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { CodeFrame, CodeGroup, CodeSource } from "@rivet-gg/components"; -import installCliCmd, { - source as installCliCmdSource, -} from "./initial-setup-install-rivet-cli-cmd.sh?shiki&lang=bash"; -import installCliPowerShell, { - source as installCliPowerShellSource, -} from "./initial-setup-install-rivet-cli-powershell.sh?shiki&lang=bash"; -import installCliSource, { - source as installCliSourceSource, -} from "./initial-setup-install-rivet-cli-source.sh?shiki&lang=bash"; -import installCliUnix, { - source as installCliUnixSource, -} from "./initial-setup-install-rivet-cli-unix.sh?shiki&lang=bash"; - -export function InstallCli() { - return ( - - - {installCliUnix} - - - {installCliCmd} - - - {installCliPowerShell} - - - {installCliSource} - - - ); -} diff --git a/frontend/apps/hub/src/components/onboarding/onboarding.tsx b/frontend/apps/hub/src/components/onboarding/onboarding.tsx deleted file mode 100644 index fc05e5504f..0000000000 --- a/frontend/apps/hub/src/components/onboarding/onboarding.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import type { Rivet } from "@rivet-gg/api-full"; -import { H1, Lead, Page } from "@rivet-gg/components"; -import { LayoutGroup, motion } from "framer-motion"; -import { Intro } from "../intro"; -import { OnboardingBackground } from "../onboarding-background"; - -interface OnboardingProps { - initialProjectName?: string; - initialStep?: number; - onFinish?: (project: Rivet.game.GameSummary) => Promise | void; -} - -export function Onboarding({ - initialProjectName, - initialStep, - onFinish, -}: OnboardingProps) { - return ( - <> - - -
-

- - Get Started - -

- - - Your system to build robust, fast, and scalable - applications on the edge. - - - - - - - - -
-
- - ); -} diff --git a/frontend/apps/hub/src/components/sections/deep-dive-section.tsx b/frontend/apps/hub/src/components/sections/deep-dive-section.tsx deleted file mode 100644 index 792809ff12..0000000000 --- a/frontend/apps/hub/src/components/sections/deep-dive-section.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import { Button, Grid, H2 } from "@rivet-gg/components"; -import { Icon, faArrowRight } from "@rivet-gg/icons"; - -export function DeepDiveSection() { - return ( - <> -

Deep dive

- - - - - - - - ); -} diff --git a/frontend/apps/hub/src/components/sections/faq-section.tsx b/frontend/apps/hub/src/components/sections/faq-section.tsx deleted file mode 100644 index 04715742af..0000000000 --- a/frontend/apps/hub/src/components/sections/faq-section.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import { - Accordion, - AccordionContent, - AccordionItem, - AccordionTrigger, - H2, - Link, - Strong, - Ul, -} from "@rivet-gg/components"; - -export function FaqSection() { - return ( - <> -

Frequently Asked Questions

- - - What is Rivet? - -

- Rivet is a multiplayert tooling that provides a - suite of tools to help you build and deploy - multiplayer projects. Rivet provides a scalable, - secure, and reliable infrastructure for: -

-
    -
  • - Dynamic Servers for auto-scaling project lobbies{" "} -
  • -
  • - DDoS mitigation and managed WebSocket SSL & - TCP+TLS termination -
  • -
  • Streamlined DevOps for teams
  • -
  • Unified logging & monitoring & analytics
  • -
  • No downtime deploys with easy rollbacks
  • -
-
-
- - - What Project Engines are supported? - - -

- Rivet supports all major project engines including - Unity, Unreal Engine, Godot. It also provides SDKs - for popular languages like C#, C++, and JavaScript, - so you can use Rivet with any project engine even if - it's your own custom engine. -

-
-
- - Is Rivet open-source? - -

- Yes, Rivet is open-source.You can - find our repositories on{" "} - - GitHub - - . We welcome contributions, bug reports, and feature - requests from the community. -

-
-
- - Is Rivet free? - -

- Yes, Rivet is free. You can use - Rivet for free with no limits on the number of - players. We offer premium support plans for teams - that require additional support. For more - information, - - please visit our pricing page - - . -

-
-
-
- - ); -} diff --git a/frontend/apps/hub/src/components/third-party-providers.tsx b/frontend/apps/hub/src/components/third-party-providers.tsx deleted file mode 100644 index a87f0fe2f0..0000000000 --- a/frontend/apps/hub/src/components/third-party-providers.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { useAuth } from "@/domains/auth/contexts/auth"; -import { UTCDate } from "@date-fns/utc"; -import * as Sentry from "@sentry/react"; -import { usePostHog } from "posthog-js/react"; -import { useEffect } from "react"; - -export function IdentifyUser() { - const posthog = usePostHog(); - const { profile } = useAuth(); - - useEffect(() => { - const identity = profile?.identity; - if (identity) { - const user = { - name: identity.displayName, - email: identity.linkedAccounts.find((x) => x.email)?.email - ?.email, - joinTs: new UTCDate(identity.joinTs).toISOString(), - avatar: identity.avatarUrl, - isAdmin: identity.isAdmin, - }; - - posthog.identify(`user:${identity.identityId}`, user); - Sentry.setUser(user); - } - }, [posthog, profile]); - - return null; -} diff --git a/frontend/apps/hub/src/domains/auth/components/feedback.tsx b/frontend/apps/hub/src/domains/auth/components/feedback.tsx deleted file mode 100644 index a3b095eb73..0000000000 --- a/frontend/apps/hub/src/domains/auth/components/feedback.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { Link as LinkCmp } from "@rivet-gg/components"; -import { Link } from "@tanstack/react-router"; - -export function Feedback() { - return ( - - - Missing something? Spot a bug? - - - ); -} diff --git a/frontend/apps/hub/src/domains/auth/contexts/auth.tsx b/frontend/apps/hub/src/domains/auth/contexts/auth.tsx deleted file mode 100644 index e34dcb9d14..0000000000 --- a/frontend/apps/hub/src/domains/auth/contexts/auth.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { IdentifyUser } from "@/components/third-party-providers"; -import { - selfProfileQueryOptions, - useIdentityTokenMutation, - useLogoutMutation, -} from "@/domains/user/queries"; -import type { Rivet } from "@rivet-gg/api-full"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { createContext, useContext } from "react"; -import { bootstrapQueryOptions } from "../queries/bootstrap"; - -export interface AuthContext { - profile: Rivet.identity.GetProfileResponse | undefined; - isProfileLoading: boolean; - logout: () => void; - refreshToken: () => Promise; -} - -const AuthContext = createContext(null); - -export function AuthProvider({ children }: { children: React.ReactNode }) { - const { mutateAsync } = useIdentityTokenMutation(); - const { - data: profile, - isRefetching, - isFetching, - } = useSuspenseQuery(selfProfileQueryOptions()); - - const { mutate: logout } = useLogoutMutation(); - - useSuspenseQuery(bootstrapQueryOptions()); - - return ( - - - {children} - - ); -} - -export function useAuth() { - const context = useContext(AuthContext); - if (!context) { - throw new Error("useAuth must be used within an AuthProvider"); - } - return context; -} diff --git a/frontend/apps/hub/src/domains/auth/forms/device-link-form.tsx b/frontend/apps/hub/src/domains/auth/forms/device-link-form.tsx deleted file mode 100644 index 2958285b8c..0000000000 --- a/frontend/apps/hub/src/domains/auth/forms/device-link-form.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { ProjectSelect } from "@/domains/project/components/project-select"; -import { useDialog } from "@/hooks/use-dialog"; -import { - FormField, - FormItem, - FormLabel, - FormMessage, - createSchemaForm, -} from "@rivet-gg/components"; -import { type UseFormReturn, useFormContext } from "react-hook-form"; -import z from "zod"; - -export const formSchema = z.object({ - projectId: z.string().min(1, "Required"), - token: z.string(), -}); - -export type FormValues = z.infer; -export type SubmitHandler = ( - values: FormValues, - form: UseFormReturn, -) => Promise; - -const { Form, Submit, Reset } = createSchemaForm(formSchema); -export { Form, Submit, Reset }; - -export const Project = () => { - const { control, setValue } = useFormContext(); - const { dialog, open, close } = useDialog.CreateProject({ - onSuccess: (data) => { - setValue("projectId", data.gameId, { - shouldDirty: true, - shouldTouch: true, - }); - close(); - }, - }); - - return ( - <> - {dialog} - ( - - Project - - - - )} - /> - - ); -}; - -export const Token = ({ value }: { value: string }) => { - const { register } = useFormContext(); - return ; -}; diff --git a/frontend/apps/hub/src/domains/auth/forms/login-form.tsx b/frontend/apps/hub/src/domains/auth/forms/login-form.tsx deleted file mode 100644 index 8b47578388..0000000000 --- a/frontend/apps/hub/src/domains/auth/forms/login-form.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import { - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, - Input, - createSchemaForm, -} from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { type UseFormReturn, useFormContext } from "react-hook-form"; -import Turnstile from "react-turnstile"; -import z from "zod"; -import { bootstrapCaptchaQueryOptions } from "../queries/bootstrap"; - -export const formSchema = z.object({ - email: z.string().email(), - captcha: z.string(), -}); - -export type FormValues = z.infer; -export type SubmitHandler = ( - values: FormValues, - form: UseFormReturn, -) => Promise; - -const { Form, Submit } = createSchemaForm(formSchema); -export { Form, Submit }; - -export const Email = () => { - const { control } = useFormContext(); - return ( - ( - - Email - - - - - - )} - /> - ); -}; - -export const Captcha = () => { - const { control } = useFormContext(); - const { data } = useSuspenseQuery(bootstrapCaptchaQueryOptions()); - - return ( - ( - - - {data.turnstile?.siteKey ? ( - { - field.onChange({ - target: { value: token }, - }); - }} - /> - ) : null} - - - - )} - /> - ); -}; diff --git a/frontend/apps/hub/src/domains/auth/forms/otp-form.tsx b/frontend/apps/hub/src/domains/auth/forms/otp-form.tsx deleted file mode 100644 index 59f183e1a8..0000000000 --- a/frontend/apps/hub/src/domains/auth/forms/otp-form.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { type UseFormReturn, useFormContext } from "react-hook-form"; -import z from "zod"; - -import { - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, - InputOTP, - InputOTPGroup, - InputOTPSlot, - createSchemaForm, -} from "@rivet-gg/components"; -import { REGEXP_ONLY_DIGITS_AND_CHARS } from "input-otp"; -import type { InputHTMLAttributes } from "react"; - -export const formSchema = z.object({ - otp: z.string().min(8).max(8), -}); - -export type FormValues = z.infer; -export type SubmitHandler = ( - values: FormValues, - form: UseFormReturn, -) => Promise; - -const { Form, Submit } = createSchemaForm(formSchema); -export { Form, Submit }; - -export const Code = (props: InputHTMLAttributes) => { - const { control } = useFormContext(); - return ( - ( - - Code - - - - - - - - - - - - - - - - - )} - /> - ); -}; diff --git a/frontend/apps/hub/src/domains/auth/queries/bootstrap.ts b/frontend/apps/hub/src/domains/auth/queries/bootstrap.ts deleted file mode 100644 index 578c00a22f..0000000000 --- a/frontend/apps/hub/src/domains/auth/queries/bootstrap.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { queryOptions } from "@tanstack/react-query"; -import { rivetClient } from "../../../queries/global"; - -export const bootstrapQueryOptions = () => { - return queryOptions({ - queryKey: ["bootstrap"], - queryFn: () => rivetClient.cloud.bootstrap(), - refetchOnWindowFocus: false, - }); -}; - -export const bootstrapOpenGbQueryOptions = () => { - return queryOptions({ - ...bootstrapQueryOptions(), - select: (data) => data.domains?.opengb || window.location.host, - }); -}; - -export const bootstrapCaptchaQueryOptions = () => { - return queryOptions({ - ...bootstrapQueryOptions(), - select: (data) => data.captcha, - }); -}; - -export const clusterQueryOptions = () => { - return queryOptions({ - ...bootstrapQueryOptions(), - select: (data) => data.cluster, - }); -}; diff --git a/frontend/apps/hub/src/domains/auth/queries/index.ts b/frontend/apps/hub/src/domains/auth/queries/index.ts deleted file mode 100644 index 2797e9ea0f..0000000000 --- a/frontend/apps/hub/src/domains/auth/queries/index.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { Rivet } from "@rivet-gg/api-full"; -import { useMutation } from "@tanstack/react-query"; -import { queryClient, rivetClient } from "../../../queries/global"; - -export const useStartEmailVerificationMutation = () => { - return useMutation({ - mutationFn: (data: Rivet.auth.identity.StartEmailVerificationRequest) => - rivetClient.auth.identity.email.startEmailVerification(data), - }); -}; - -export const useCompleteEmailVerificationMutation = ( - opts: { - onSuccess?: ( - data: Rivet.auth.identity.CompleteEmailVerificationResponse, - ) => void; - } = {}, -) => { - return useMutation({ - mutationFn: ( - data: Rivet.auth.identity.CompleteEmailVerificationRequest, - ) => rivetClient.auth.identity.email.completeEmailVerification(data), - ...opts, - }); -}; - -export const deviceLinkTokenQueryOptions = (deviceLinkToken: string) => { - return { - queryKey: ["deviceLinkToken", deviceLinkToken], - queryFn: () => rivetClient.cloud.devices.links.get({ deviceLinkToken }), - }; -}; - -export const useCompleteDeviceLinkMutation = () => { - return useMutation({ - mutationFn: ( - data: Rivet.cloud.devices.links.CompleteDeviceLinkRequest, - ) => rivetClient.cloud.devices.links.complete(data), - onSuccess: (_, values) => { - queryClient.invalidateQueries( - deviceLinkTokenQueryOptions(values.deviceLinkToken), - ); - }, - }); -}; diff --git a/frontend/apps/hub/src/domains/auth/views/login-view/email-step.tsx b/frontend/apps/hub/src/domains/auth/views/login-view/email-step.tsx deleted file mode 100644 index 567107366a..0000000000 --- a/frontend/apps/hub/src/domains/auth/views/login-view/email-step.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { AuthCard } from "@/components/auth-card"; -import * as LoginForm from "@/domains/auth/forms/login-form"; -import { - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, - Flex, - Link, - MutedText, -} from "@rivet-gg/components"; - -interface EmailStepProps { - onSubmit: LoginForm.SubmitHandler; -} - -export const EmailStep = ({ onSubmit }: EmailStepProps) => { - return ( - - - - Login - - Enter your email below to login to your account. - - - - - - - - By clicking Continue, you agree to the Rivet{" "} - - Terms of Service - {" "} - and{" "} - - Privacy Policy - - . - - - - - Continue - - - - ); -}; diff --git a/frontend/apps/hub/src/domains/auth/views/login-view/hooks.ts b/frontend/apps/hub/src/domains/auth/views/login-view/hooks.ts deleted file mode 100644 index 61f101743a..0000000000 --- a/frontend/apps/hub/src/domains/auth/views/login-view/hooks.ts +++ /dev/null @@ -1,95 +0,0 @@ -import type { SubmitHandler as FormSubmitHandler } from "@/domains/auth/forms/otp-form"; -import { useCompleteEmailVerificationMutation } from "@/domains/auth/queries"; -import { Rivet } from "@rivet-gg/api-full"; -import * as Sentry from "@sentry/react"; -import { useQueryClient } from "@tanstack/react-query"; -import { useCallback } from "react"; -import { useAuth } from "../../contexts/auth"; - -const RESPONSE_MAP = { - [Rivet.auth.CompleteStatus.SwitchIdentity]: { - type: Rivet.auth.CompleteStatus.SwitchIdentity, - }, - [Rivet.auth.CompleteStatus.LinkedAccountAdded]: { - type: Rivet.auth.CompleteStatus.LinkedAccountAdded, - }, - [Rivet.auth.CompleteStatus.AlreadyComplete]: { - type: "error", - message: "This verification session has already been completed.", - }, - [Rivet.auth.CompleteStatus.Expired]: { - type: "error", - message: "This verification session has expired. Please try again.", - }, - [Rivet.auth.CompleteStatus.TooManyAttempts]: { - type: "error", - message: "Too many failed attempts. Try again later.", - }, - [Rivet.auth.CompleteStatus.Incorrect]: { - type: "error", - message: "The verification code given is incorrect.", - }, - default: { - type: "error", - message: "Unknown error", - }, -} as const; - -export interface OtpFormSubmitHandlerArgs { - verificationId: string | undefined; - onSuccess?: () => void; -} - -export const useOtpFormSubmitHandler = ({ - onSuccess, - verificationId, -}: OtpFormSubmitHandlerArgs) => { - const { refreshToken } = useAuth(); - const queryClient = useQueryClient(); - const { mutateAsync } = useCompleteEmailVerificationMutation(); - - const callback: FormSubmitHandler = useCallback( - async (values, form) => { - if (!verificationId) { - return form.setError("otp", { - type: "manual", - message: "Unknown error. Please try again.", - }); - } - try { - const response = await mutateAsync({ - verificationId, - code: values.otp, - }); - - const translatedResponse = - RESPONSE_MAP[response.status] || RESPONSE_MAP.default; - - if (translatedResponse.type === "error") { - return form.setError("otp", { - type: "manual", - message: translatedResponse.message, - }); - } - await refreshToken(); - await queryClient.invalidateQueries({ refetchType: "all" }); - return onSuccess?.(); - } catch (error) { - Sentry.captureException(error); - return form.setError("otp", { - type: "manual", - message: "Invalid verification code", - }); - } - }, - [ - mutateAsync, - onSuccess, - queryClient.invalidateQueries, - refreshToken, - verificationId, - ], - ); - - return callback; -}; diff --git a/frontend/apps/hub/src/domains/auth/views/login-view/login-view.tsx b/frontend/apps/hub/src/domains/auth/views/login-view/login-view.tsx deleted file mode 100644 index 6b340a07bd..0000000000 --- a/frontend/apps/hub/src/domains/auth/views/login-view/login-view.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import type { FormValues as LoginFormValues } from "@/domains/auth/forms/login-form"; -import { useStartEmailVerificationMutation } from "@/domains/auth/queries"; -import { EmailStep } from "./email-step"; -import { - type OtpFormSubmitHandlerArgs, - useOtpFormSubmitHandler, -} from "./hooks"; -import { OtpStep } from "./otp-step"; - -interface LoginViewProps { - onSuccess?: OtpFormSubmitHandlerArgs["onSuccess"]; -} - -export const LoginView = ({ onSuccess }: LoginViewProps) => { - const { - mutateAsync: startEmailVerif, - data: emailVerifData, - reset: resetEmailVerif, - isSuccess, - } = useStartEmailVerificationMutation(); - - const handleOtpSubmit = useOtpFormSubmitHandler({ - verificationId: emailVerifData?.verificationId, - onSuccess, - }); - - const handleEmailSubmit = async (values: LoginFormValues) => { - await startEmailVerif({ - email: values.email, - captcha: { turnstile: { clientResponse: values.captcha } }, - }); - }; - - if (isSuccess) { - return ( - - ); - } - - return ; -}; diff --git a/frontend/apps/hub/src/domains/auth/views/login-view/otp-step.tsx b/frontend/apps/hub/src/domains/auth/views/login-view/otp-step.tsx deleted file mode 100644 index 051aa7dd65..0000000000 --- a/frontend/apps/hub/src/domains/auth/views/login-view/otp-step.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import * as OtpForm from "@/domains/auth/forms/otp-form"; -import { - Button, - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, - Flex, -} from "@rivet-gg/components"; - -interface OtpStepProps { - onSubmit: OtpForm.SubmitHandler; - onCancel: () => void; -} - -export const OtpStep = ({ onSubmit, onCancel }: OtpStepProps) => { - return ( - - - - Welcome to Rivet! - - Check your email for a verification code from - hello@rivet.gg and paste it into the area below. - - - - - - - - - Continue - - - - - ); -}; diff --git a/frontend/apps/hub/src/domains/group/components/dialogs/confirm-leave-group-dialog.tsx b/frontend/apps/hub/src/domains/group/components/dialogs/confirm-leave-group-dialog.tsx deleted file mode 100644 index dea5e33a92..0000000000 --- a/frontend/apps/hub/src/domains/group/components/dialogs/confirm-leave-group-dialog.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { groupProjectsQueryOptions } from "@/domains/project/queries"; -import { - Button, - Code, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, - Text, -} from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { useGroupLeaveMutation } from "../../queries"; - -interface ConfirmLeaveGroupDialogContentProps { - groupId: string; - onSuccess?: () => void; -} - -export default function ConfirmLeaveGroupDialogContent({ - groupId, - onSuccess, -}: ConfirmLeaveGroupDialogContentProps) { - const { data: group } = useSuspenseQuery( - groupProjectsQueryOptions(groupId), - ); - const { mutate, isPending } = useGroupLeaveMutation({ - onSuccess, - }); - - return ( - <> - - Confirm - -
- - Are you sure you want to leave group - {group?.displayName}? - -
-
-
- - - - - ); -} diff --git a/frontend/apps/hub/src/domains/group/components/dialogs/confirm-member-ban-dialog.tsx b/frontend/apps/hub/src/domains/group/components/dialogs/confirm-member-ban-dialog.tsx deleted file mode 100644 index 4e36472825..0000000000 --- a/frontend/apps/hub/src/domains/group/components/dialogs/confirm-member-ban-dialog.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { groupProjectsQueryOptions } from "@/domains/project/queries"; -import { - Button, - Code, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, - Strong, - Text, -} from "@rivet-gg/components"; -import { useQuery, useSuspenseQuery } from "@tanstack/react-query"; -import { - groupMemberQueryOptions, - useGroupBanMemberMutation, -} from "../../queries"; - -interface ConfirmMemberBanDialogContentProps { - groupId: string; - identityId: string; - onSuccess?: () => void; -} - -export default function ConfirmMemberBanDialogContent({ - groupId, - identityId, - onSuccess, -}: ConfirmMemberBanDialogContentProps) { - const { data: group } = useSuspenseQuery( - groupProjectsQueryOptions(groupId), - ); - const { data: groupMember } = useQuery( - groupMemberQueryOptions({ identityId, groupId }), - ); - const { mutate, isPending } = useGroupBanMemberMutation({ - onSuccess, - }); - - return ( - <> - - Confirm Member Ban - -
- - Are you sure you want to ban{" "} - {groupMember?.identity.displayName}{" "} - from group {group?.displayName}? - -
-
-
- - - - - ); -} diff --git a/frontend/apps/hub/src/domains/group/components/dialogs/confirm-member-kick-dialog.tsx b/frontend/apps/hub/src/domains/group/components/dialogs/confirm-member-kick-dialog.tsx deleted file mode 100644 index e8b2cb03ab..0000000000 --- a/frontend/apps/hub/src/domains/group/components/dialogs/confirm-member-kick-dialog.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { groupProjectsQueryOptions } from "@/domains/project/queries"; -import { - Button, - Code, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, - Strong, - Text, -} from "@rivet-gg/components"; -import { useQuery, useSuspenseQuery } from "@tanstack/react-query"; -import { - groupMemberQueryOptions, - useGroupKickMemberMutation, -} from "../../queries"; - -interface ConfirmMemberKickDialogContentProps { - groupId: string; - identityId: string; - onSuccess?: () => void; -} - -export default function ConfirmMemberKickDialogContent({ - groupId, - identityId, - onSuccess, -}: ConfirmMemberKickDialogContentProps) { - const { data: group } = useSuspenseQuery( - groupProjectsQueryOptions(groupId), - ); - const { data: groupMember } = useQuery( - groupMemberQueryOptions({ identityId, groupId }), - ); - const { mutate, isPending } = useGroupKickMemberMutation({ - onSuccess, - }); - - return ( - <> - - Confirm Member Kick - -
- - Are you sure you want to kick{" "} - {groupMember?.identity.displayName}{" "} - from group {group?.displayName}? - -
-
-
- - - - - ); -} diff --git a/frontend/apps/hub/src/domains/group/components/dialogs/confirm-transfer-ownership-dialog.tsx b/frontend/apps/hub/src/domains/group/components/dialogs/confirm-transfer-ownership-dialog.tsx deleted file mode 100644 index 3a36b185c2..0000000000 --- a/frontend/apps/hub/src/domains/group/components/dialogs/confirm-transfer-ownership-dialog.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { groupProjectsQueryOptions } from "@/domains/project/queries"; -import { GuardEnterprise } from "@/lib/guards"; -import { - Button, - Code, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, - Link, - Strong, - Text, -} from "@rivet-gg/components"; -import { useQuery, useSuspenseQuery } from "@tanstack/react-query"; -import { - groupMemberQueryOptions, - useGroupTransferOwnershipMutation, -} from "../../queries"; - -interface ContentProps { - groupId: string; - identityId: string; - onSuccess?: () => void; -} - -export default function ConfirmTransferOwnershipDialogContent({ - groupId, - identityId, - onSuccess, -}: ContentProps) { - const { data: group } = useSuspenseQuery( - groupProjectsQueryOptions(groupId), - ); - const { data: groupMember } = useQuery( - groupMemberQueryOptions({ identityId, groupId }), - ); - const { mutate, isPending } = useGroupTransferOwnershipMutation({ - onSuccess, - }); - - return ( - <> - - Confirm Ownership Transfer - -
- - Are you sure you want to transfer ownership of group{" "} - {group?.displayName}? This action{" "} - CANNOT be undone. - - - - - As a developer group, transferring ownership - will cause all billing related emails to be - sent to the new owner. Your bank account - information will stay attached to the group - unless removed by a Rivet employee. - - - - - Contact{" "} - - Support - {" "} - for more info. - - - New owner:{" "} - {groupMember?.identity.displayName} - -
-
-
- - - - - ); -} diff --git a/frontend/apps/hub/src/domains/group/components/dialogs/create-group-dialog.tsx b/frontend/apps/hub/src/domains/group/components/dialogs/create-group-dialog.tsx deleted file mode 100644 index ee468bbd3c..0000000000 --- a/frontend/apps/hub/src/domains/group/components/dialogs/create-group-dialog.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import * as GroupCreateForm from "@/domains/group/forms/group-create-form"; -import type { Rivet } from "@rivet-gg/api-full"; -import { - DialogFooter, - DialogHeader, - DialogTitle, - Flex, -} from "@rivet-gg/components"; -import { useGroupCreateMutation } from "../../queries"; - -interface CreateGroupDialogContentProps { - onSuccess?: (data: Rivet.group.CreateResponse) => void; -} - -export default function CreateGroupDialogContent({ - onSuccess, -}: CreateGroupDialogContentProps) { - const { mutateAsync } = useGroupCreateMutation({ - onSuccess, - }); - - return ( - <> - { - await mutateAsync({ - displayName: values.name, - }); - }} - defaultValues={{ name: "" }} - > - - Create New Team - - - - - - - Create - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/group/components/dialogs/create-group-invite-dialog.tsx b/frontend/apps/hub/src/domains/group/components/dialogs/create-group-invite-dialog.tsx deleted file mode 100644 index b8a17e2505..0000000000 --- a/frontend/apps/hub/src/domains/group/components/dialogs/create-group-invite-dialog.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import * as GroupInviteForm from "@/domains/group/forms/group-invite-form"; -import { - Button, - CopyArea, - DialogFooter, - DialogHeader, - DialogTitle, - Flex, - Label, - Text, - timing, -} from "@rivet-gg/components"; -import { useGroupInviteMutation } from "../../queries"; - -interface CreateGroupInviteDialogContentContentProps { - groupId: string; - onClose?: () => void; -} - -export default function CreateGroupInviteDialogContent({ - groupId, - onClose, -}: CreateGroupInviteDialogContentContentProps) { - const { mutateAsync, data } = useGroupInviteMutation(); - - if (data) { - return ( - <> - - Create Group Invite - - - - Share this code or link to allow people to join your - group. - - - - - - - - - - - - - - - ); - } - - return ( - <> - { - await mutateAsync({ - groupId, - ttl: values.expTime === 0 ? undefined : values.expTime, - useCount: values.isInfinite - ? undefined - : values.usageCount, - }); - }} - defaultValues={{ - isInfinite: true, - expTime: timing.minutes(30), - usageCount: 10, - }} - > - - Create Group Invite - - - - - - - - - Create - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/group/components/group-avatar.tsx b/frontend/apps/hub/src/domains/group/components/group-avatar.tsx deleted file mode 100644 index a89a95c8f0..0000000000 --- a/frontend/apps/hub/src/domains/group/components/group-avatar.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import type { Rivet } from "@rivet-gg/api-full"; -import { - Avatar, - AvatarFallback, - AvatarImage, - type AvatarProps, -} from "@rivet-gg/components"; - -interface GroupAvatarProps - extends Pick, - AvatarProps {} - -export function GroupAvatar({ - avatarUrl, - displayName, - ...props -}: GroupAvatarProps) { - return ( - - - {displayName[0]} - - ); -} diff --git a/frontend/apps/hub/src/domains/group/components/group-create-card.tsx b/frontend/apps/hub/src/domains/group/components/group-create-card.tsx deleted file mode 100644 index 7928cb2582..0000000000 --- a/frontend/apps/hub/src/domains/group/components/group-create-card.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { Button, Card, CardFooter } from "@rivet-gg/components"; -import { Link } from "@tanstack/react-router"; - -export function GroupCreateCard() { - return ( - <> - - - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/group/components/group-empty-alert.tsx b/frontend/apps/hub/src/domains/group/components/group-empty-alert.tsx deleted file mode 100644 index a7a11086fd..0000000000 --- a/frontend/apps/hub/src/domains/group/components/group-empty-alert.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { - Alert, - AlertDescription, - AlertTitle, - Button, - Flex, -} from "@rivet-gg/components"; -import { Icon, faGhost } from "@rivet-gg/icons"; -import { Link } from "@tanstack/react-router"; - -interface GroupEmptyAlertProps { - groupId: string; - showCreateButton?: boolean; -} - -export function GroupEmptyAlert({ - groupId, - showCreateButton, -}: GroupEmptyAlertProps) { - return ( - <> - - - It's a ghost town! - - - This group doesn't have any projects yet. Get started by - creating a new one. - {showCreateButton ? ( - - ) : null} - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/group/components/group-image-settings-card.tsx b/frontend/apps/hub/src/domains/group/components/group-image-settings-card.tsx deleted file mode 100644 index 0dbca8ff03..0000000000 --- a/frontend/apps/hub/src/domains/group/components/group-image-settings-card.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import * as GroupImageForm from "@/domains/group/forms/group-image-form"; -import { useAvatarUploadMutation } from "@/domains/group/queries"; -import { - Card, - CardContent, - CardFooter, - CardHeader, - CardTitle, - Skeleton, -} from "@rivet-gg/components"; - -interface GroupImageSettingsCardProps { - groupId: string; -} - -export function GroupImageSettingsCard({ - groupId, -}: GroupImageSettingsCardProps) { - const { mutateAsync } = useAvatarUploadMutation(groupId); - return ( - { - try { - await mutateAsync({ file: values.image }); - } catch { - form.setError("image", { - type: "manual", - message: "An error occurred while uploading the image", - }); - } - }} - defaultValues={{ image: undefined }} - > - - - Team Image - - - - - - Save - - - - ); -} - -GroupImageSettingsCard.Skeleton = function GroupImageSettingsCard() { - return ; -}; diff --git a/frontend/apps/hub/src/domains/group/components/group-member-settings-menu.tsx b/frontend/apps/hub/src/domains/group/components/group-member-settings-menu.tsx deleted file mode 100644 index fc069e7521..0000000000 --- a/frontend/apps/hub/src/domains/group/components/group-member-settings-menu.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { groupOnwerQueryOptions } from "@/domains/project/queries"; -import { selfProfileIdentityIdQueryOptions } from "@/domains/user/queries"; -import { - Button, - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from "@rivet-gg/components"; -import { Icon, faEllipsisVertical } from "@rivet-gg/icons"; -import { useSuspenseQuery } from "@tanstack/react-query"; - -interface GroupMemberInfo { - identityId: string; - groupId: string; -} - -interface GroupMemberSettingsMenuProps extends GroupMemberInfo { - onTransferOwnership?: (data: GroupMemberInfo) => void; - onKick?: (data: GroupMemberInfo) => void; - onBan?: (data: GroupMemberInfo) => void; -} - -export function GroupMemberSettingsMenu({ - groupId, - identityId, - onTransferOwnership, - onKick, - onBan, -}: GroupMemberSettingsMenuProps) { - const { data: selfProfileIdentityId } = useSuspenseQuery( - selfProfileIdentityIdQueryOptions(), - ); - const { data: groupOwnerIdentityId } = useSuspenseQuery( - groupOnwerQueryOptions(groupId), - ); - if ( - selfProfileIdentityId !== groupOwnerIdentityId || - groupOwnerIdentityId === identityId - ) { - return null; - } - return ( - - - - - - {groupOwnerIdentityId !== identityId ? ( - - onTransferOwnership?.({ groupId, identityId }) - } - > - Transfer ownership - - ) : null} - { - onKick?.({ groupId, identityId }); - }} - > - Kick - - { - onBan?.({ groupId, identityId }); - }} - > - Ban - - - - ); -} diff --git a/frontend/apps/hub/src/domains/group/components/group-name-settings-card.tsx b/frontend/apps/hub/src/domains/group/components/group-name-settings-card.tsx deleted file mode 100644 index 346dd9240f..0000000000 --- a/frontend/apps/hub/src/domains/group/components/group-name-settings-card.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import * as GroupNameForm from "@/domains/group/forms/group-name-form"; -import { useGroupUpdateProfileMutation } from "@/domains/group/queries"; -import { groupProjectsQueryOptions } from "@/domains/project/queries"; -import { - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, - Skeleton, -} from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; - -interface GroupNameSettingsCardProps { - groupId: string; -} - -export function GroupNameSettingsCard({ groupId }: GroupNameSettingsCardProps) { - const { data } = useSuspenseQuery(groupProjectsQueryOptions(groupId)); - const { mutateAsync } = useGroupUpdateProfileMutation(); - return ( - { - return mutateAsync({ groupId, displayName: values.name }); - }} - defaultValues={{ name: data?.displayName }} - > - - - Team Name - - Used to identify your team in various parts of the - ecosystem. - - - - - - - Save - - - - ); -} - -GroupNameSettingsCard.Skeleton = function GroupNameSettingsCardSkeleton() { - return ; -}; diff --git a/frontend/apps/hub/src/domains/group/components/group-select.tsx b/frontend/apps/hub/src/domains/group/components/group-select.tsx deleted file mode 100644 index d4ac152d8a..0000000000 --- a/frontend/apps/hub/src/domains/group/components/group-select.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { GroupAvatar } from "@/domains/group/components/group-avatar"; -import { projectsByGroupQueryOptions } from "@/domains/project/queries"; -import { - Flex, - Select, - SelectContent, - SelectItem, - SelectSeparator, - SelectTrigger, - SelectValue, -} from "@rivet-gg/components"; -import { Icon, faCirclePlus } from "@rivet-gg/icons"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { type ComponentProps, useCallback } from "react"; - -interface GroupSelectProps extends ComponentProps { - showCreateGroup?: boolean; - onCreateClick?: () => void; - variant?: ComponentProps["variant"]; -} - -export function GroupSelect({ - showCreateGroup, - onCreateClick, - onValueChange, - variant, - ...props -}: GroupSelectProps) { - const { data } = useSuspenseQuery(projectsByGroupQueryOptions()); - - const handleValueChange = useCallback( - (value: string) => { - if (value === "create") { - onCreateClick?.(); - return; - } - onValueChange?.(value); - }, - [onCreateClick, onValueChange], - ); - - return ( - - ); -} diff --git a/frontend/apps/hub/src/domains/group/components/group.tsx b/frontend/apps/hub/src/domains/group/components/group.tsx deleted file mode 100644 index 57250e660b..0000000000 --- a/frontend/apps/hub/src/domains/group/components/group.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import type { GroupProjects } from "@/domains/project/queries"; -import { - Button, - Card, - CardContent, - CardHeader, - Flex, - Grid, - LargeText, - Skeleton, -} from "@rivet-gg/components"; -import { Icon, faArrowRight, faPlus } from "@rivet-gg/icons"; - -import { ProjectTile } from "@/domains/project/components/project-tile"; -import { Link } from "@tanstack/react-router"; -import { GroupAvatar } from "./group-avatar"; -import { GroupEmptyAlert } from "./group-empty-alert"; - -interface GroupProps extends GroupProjects {} - -export function Group(props: GroupProps) { - const { groupId, displayName, avatarUrl, projects, isDeveloper } = props; - - return ( - - - - - - - {displayName} - - - - {isDeveloper ? ( - - ) : null} - - - - - - {projects.length === 0 ? ( - - ) : ( - - {projects.map((project) => ( - - - - ))} - - )} - - - ); -} - -Group.Skeleton = () => { - return ; -}; diff --git a/frontend/apps/hub/src/domains/group/components/no-groups-alert.tsx b/frontend/apps/hub/src/domains/group/components/no-groups-alert.tsx deleted file mode 100644 index 1bf6a96c2d..0000000000 --- a/frontend/apps/hub/src/domains/group/components/no-groups-alert.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { - Alert, - AlertDescription, - AlertTitle, - Button, - Flex, -} from "@rivet-gg/components"; -import { Icon, faGhost } from "@rivet-gg/icons"; -import { Link } from "@tanstack/react-router"; - -export function NoGroupsAlert() { - return ( - <> - - - It's a ghost town! - - - You are not a member of any team yet. Get started by - creating a new team. - - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/group/forms/group-create-form.tsx b/frontend/apps/hub/src/domains/group/forms/group-create-form.tsx deleted file mode 100644 index 59bcf5dab3..0000000000 --- a/frontend/apps/hub/src/domains/group/forms/group-create-form.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { safeAsyncValidation } from "@/lib/async-validation"; -import { TraversableErrors, VALIDATION_ERRORS } from "@/lib/traversable-errors"; -import { rivetClient } from "@/queries/global"; -import { - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, - Input, - createSchemaForm, -} from "@rivet-gg/components"; -import { type UseFormReturn, useFormContext } from "react-hook-form"; -import z from "zod"; - -export const formSchema = z - .object({ - name: z.string().max(25), - }) - .superRefine(async (arg, ctx) => { - await safeAsyncValidation(ctx, async () => { - const res = await rivetClient.cloud.groups.validate({ - displayName: arg.name, - }); - const errors = new TraversableErrors(VALIDATION_ERRORS.GROUP); - errors.load(res.errors.map((e) => e.path)); - - if (!errors.isEmpty()) { - ctx.addIssue({ - path: ["name"], - code: z.ZodIssueCode.custom, - message: errors.findFormatted()[0] || "", - }); - } - }); - - return z.NEVER; - }); - -export type FormValues = z.infer; -export type SubmitHandler = ( - values: FormValues, - form: UseFormReturn, -) => Promise; - -const { Form, Submit } = createSchemaForm(formSchema); -export { Form, Submit }; - -export const Name = ({ className }: { className?: string }) => { - const { control } = useFormContext(); - return ( - ( - - Team Name - - - - - - )} - /> - ); -}; diff --git a/frontend/apps/hub/src/domains/group/forms/group-image-form.tsx b/frontend/apps/hub/src/domains/group/forms/group-image-form.tsx deleted file mode 100644 index dc90eaffed..0000000000 --- a/frontend/apps/hub/src/domains/group/forms/group-image-form.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { - FileInput, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, - createSchemaForm, - fileSize, -} from "@rivet-gg/components"; -import { type UseFormReturn, useFormContext } from "react-hook-form"; -import z from "zod"; - -const allowedTypes = ["image/png", "image/jpeg"]; - -export const formSchema = z.object({ - image: z - .custom() - .refine( - (file) => file.size <= fileSize.megabytes(2), - "File size should be less than 2MB.", - ) - .refine( - (file) => allowedTypes.includes(file.type), - `File type should be one of ${allowedTypes.join(", ")}`, - ), -}); - -export type FormValues = z.infer; -export type SubmitHandler = ( - values: FormValues, - form: UseFormReturn, -) => Promise; - -const { Form, Submit } = createSchemaForm(formSchema); -export { Form, Submit }; - -export const Image = () => { - const { control } = useFormContext(); - return ( - ( - - Image - - - name="image" - field={field} - accept={allowedTypes.join(", ")} - /> - - - - )} - /> - ); -}; diff --git a/frontend/apps/hub/src/domains/group/forms/group-invite-form.tsx b/frontend/apps/hub/src/domains/group/forms/group-invite-form.tsx deleted file mode 100644 index a6d3c1a9e6..0000000000 --- a/frontend/apps/hub/src/domains/group/forms/group-invite-form.tsx +++ /dev/null @@ -1,135 +0,0 @@ -import { - Flex, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, - Input, - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, - Switch, - createSchemaForm, - timing, -} from "@rivet-gg/components"; -import { type UseFormReturn, useFormContext } from "react-hook-form"; -import z from "zod"; - -const expirationValues = [ - { label: "30 minutes", value: timing.minutes(30) }, - { label: "1 hour", value: timing.hours(1) }, - { label: "6 hours", value: timing.hours(6) }, - { label: "12 hours", value: timing.hours(12) }, - { label: "1 day", value: timing.days(1) }, - { label: "1 week", value: timing.days(7) }, - { label: "1 month", value: timing.days(30) }, - { label: "never", value: 0 }, -]; - -export const formSchema = z.object({ - expTime: z.coerce.number(), - isInfinite: z.boolean(), - usageCount: z.coerce.number().min(1).max(5000).default(10), -}); - -export type FormValues = z.infer; -export type SubmitHandler = ( - values: FormValues, - form: UseFormReturn, -) => Promise; - -const { Form, Submit } = createSchemaForm(formSchema); -export { Form, Submit }; - -export const ExpirationTime = () => { - const { control } = useFormContext(); - return ( - ( - - Expire after - - - - )} - /> - ); -}; - -export const Infinite = () => { - const { control } = useFormContext(); - return ( - ( - - - - Infinite use - - - - )} - /> - ); -}; - -export const UsageCount = () => { - const { control, watch } = useFormContext(); - - const isInfinite = watch("isInfinite"); - - if (isInfinite) { - return null; - } - - return ( - ( - - Max number of uses - - - - - - )} - /> - ); -}; diff --git a/frontend/apps/hub/src/domains/group/forms/group-name-form.tsx b/frontend/apps/hub/src/domains/group/forms/group-name-form.tsx deleted file mode 100644 index e0cf54892f..0000000000 --- a/frontend/apps/hub/src/domains/group/forms/group-name-form.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, - Input, - createSchemaForm, -} from "@rivet-gg/components"; -import { type UseFormReturn, useFormContext } from "react-hook-form"; -import z from "zod"; - -export const formSchema = z.object({ - name: z.string().max(25), -}); - -export type FormValues = z.infer; -export type SubmitHandler = ( - values: FormValues, - form: UseFormReturn, -) => Promise; - -const { Form, Submit } = createSchemaForm(formSchema); -export { Form, Submit }; - -export const Name = () => { - const { control } = useFormContext(); - return ( - ( - - Name - - - - - - )} - /> - ); -}; diff --git a/frontend/apps/hub/src/domains/group/queries/index.ts b/frontend/apps/hub/src/domains/group/queries/index.ts deleted file mode 100644 index d874816e18..0000000000 --- a/frontend/apps/hub/src/domains/group/queries/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./mutations"; -export * from "./query-options"; diff --git a/frontend/apps/hub/src/domains/group/queries/mutations.ts b/frontend/apps/hub/src/domains/group/queries/mutations.ts deleted file mode 100644 index fa36098c2d..0000000000 --- a/frontend/apps/hub/src/domains/group/queries/mutations.ts +++ /dev/null @@ -1,215 +0,0 @@ -import { projectsByGroupQueryOptions } from "@/domains/project/queries"; -import { isRivetError } from "@/lib/utils"; -import { queryClient, rivetClient } from "@/queries/global"; -import type { Rivet } from "@rivet-gg/api-full"; -import { toast } from "@rivet-gg/components"; -import { useMutation } from "@tanstack/react-query"; -import { useNavigate } from "@tanstack/react-router"; -import { groupMembersQueryOptions } from "./query-options"; - -export const useGroupUpdateProfileMutation = () => { - return useMutation({ - mutationFn: ({ - groupId, - ...data - }: Rivet.group.UpdateProfileRequest & { groupId: string }) => - rivetClient.group.updateProfile(groupId, data), - onSuccess: async (_, variables) => { - return Promise.all([ - queryClient.invalidateQueries( - groupMembersQueryOptions(variables.groupId), - ), - queryClient.invalidateQueries(projectsByGroupQueryOptions()), - ]); - }, - }); -}; - -const useAvatarUploadCompleteMutation = () => { - return useMutation({ - mutationFn: ({ - groupId, - uploadId, - }: { - groupId: string; - uploadId: string; - }) => rivetClient.group.completeAvatarUpload(groupId, uploadId), - onSuccess(_, variables) { - return Promise.all([ - queryClient.invalidateQueries( - groupMembersQueryOptions(variables.groupId), - ), - queryClient.invalidateQueries(projectsByGroupQueryOptions()), - ]); - }, - }); -}; - -export const useAvatarUploadMutation = (groupId: string) => { - const { mutateAsync } = useAvatarUploadCompleteMutation(); - return useMutation({ - mutationFn: ({ file }: { file: File }) => - rivetClient.group.prepareAvatarUpload({ - mime: file.type, - contentLength: file.size, - path: file.name, - }), - onSuccess: async (response, data) => { - await fetch(response.presignedRequest.url, { - method: "PUT", - body: data.file, - mode: "cors", - headers: { - "Content-Type": data.file.type, - }, - }); - await mutateAsync({ - groupId: groupId, - uploadId: response.uploadId, - }); - }, - }); -}; - -export const useGroupTransferOwnershipMutation = ({ - onSuccess, -}: { - onSuccess?: () => void; -} = {}) => { - return useMutation({ - mutationFn: ({ - groupId, - ...rest - }: { groupId: string } & Rivet.group.TransferOwnershipRequest) => - rivetClient.group.transferOwnership(groupId, rest), - onSuccess: async (_, variables) => { - await Promise.all([ - queryClient.invalidateQueries(projectsByGroupQueryOptions()), - queryClient.invalidateQueries( - groupMembersQueryOptions(variables.groupId), - ), - ]); - onSuccess?.(); - }, - }); -}; - -export const useGroupKickMemberMutation = ({ - onSuccess, -}: { - onSuccess?: () => void; -} = {}) => { - return useMutation({ - mutationFn: ({ - groupId, - identityId, - }: { - groupId: string; - identityId: string; - }) => rivetClient.group.kickMember(groupId, identityId), - onSuccess: async (_, variables) => { - await Promise.all([ - queryClient.invalidateQueries(projectsByGroupQueryOptions()), - queryClient.invalidateQueries( - groupMembersQueryOptions(variables.groupId), - ), - ]); - onSuccess?.(); - }, - }); -}; - -export const useGroupBanMemberMutation = ({ - onSuccess, -}: { - onSuccess?: () => void; -} = {}) => { - return useMutation({ - mutationFn: ({ - groupId, - identityId, - }: { - groupId: string; - identityId: string; - }) => rivetClient.group.banIdentity(groupId, identityId), - onSuccess: async (_, variables) => { - await Promise.all([ - queryClient.invalidateQueries(projectsByGroupQueryOptions()), - queryClient.invalidateQueries( - groupMembersQueryOptions(variables.groupId), - ), - ]); - onSuccess?.(); - }, - }); -}; - -export const useGroupInviteMutation = () => { - return useMutation({ - mutationFn: ({ - groupId, - ...rest - }: { groupId: string } & Rivet.group.CreateInviteRequest) => - rivetClient.group.invites.createInvite(groupId, rest), - }); -}; - -export const useGroupCreateMutation = ({ - onSuccess, -}: { - onSuccess?: (data: Rivet.group.CreateResponse) => void; -} = {}) => { - return useMutation({ - mutationFn: (data: Rivet.group.CreateRequest) => - rivetClient.group.create(data), - onSuccess: async (data) => { - await queryClient.invalidateQueries({ - ...projectsByGroupQueryOptions(), - refetchType: "all", - }); - onSuccess?.(data); - }, - }); -}; - -export const useGroupInviteAcceptMutation = () => { - const navigate = useNavigate(); - return useMutation({ - mutationFn: (inviteId: string) => - rivetClient.group.invites.consumeInvite(inviteId), - onSuccess: async (data) => { - await queryClient.invalidateQueries(projectsByGroupQueryOptions()); - if (data.groupId) { - navigate({ - to: "/teams/$groupId", - params: { groupId: data.groupId }, - }); - } - }, - meta: { - hideErrorToast: true, - }, - }); -}; - -export const useGroupLeaveMutation = ({ - onSuccess, -}: { - onSuccess?: () => void; -} = {}) => { - return useMutation({ - mutationFn: (groupId: string) => rivetClient.group.leave(groupId), - onSuccess: async () => { - await queryClient.invalidateQueries(projectsByGroupQueryOptions()); - onSuccess?.(); - }, - onError: (error) => { - if (isRivetError(error)) { - return toast.error("Failed to leave team", { - description: error.body.message, - }); - } - return toast.error("Failed to leave team."); - }, - }); -}; diff --git a/frontend/apps/hub/src/domains/group/queries/query-options.ts b/frontend/apps/hub/src/domains/group/queries/query-options.ts deleted file mode 100644 index d9358e0deb..0000000000 --- a/frontend/apps/hub/src/domains/group/queries/query-options.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { rivetClient, rivetEeClient } from "@/queries/global"; -import { getMetaWatchIndex } from "@/queries/utils"; -import { queryOptions } from "@tanstack/react-query"; - -export const groupMembersQueryOptions = (groupId: string) => { - return queryOptions({ - queryKey: ["group", groupId], - queryFn: ({ meta, signal }) => - rivetClient.group.getMembers( - groupId, - { - watchIndex: getMetaWatchIndex(meta), - }, - { abortSignal: signal }, - ), - }); -}; - -export const groupBillingQueryOptions = (groupId: string) => { - return queryOptions({ - queryKey: ["group", groupId, "billing"], - queryFn: ({ signal }) => - rivetEeClient.ee.cloud.groups.billing.get( - groupId, - {}, - { - abortSignal: signal, - }, - ), - }); -}; - -export const groupInviteQueryOptions = (inviteId: string) => { - return queryOptions({ - queryKey: ["groupInvite", inviteId], - queryFn: ({ signal }) => - rivetClient.group.invites.getInvite(inviteId, { - abortSignal: signal, - }), - }); -}; - -export const groupMemberQueryOptions = ({ - groupId, - identityId, -}: { - groupId: string; - identityId: string; -}) => { - return queryOptions({ - ...groupMembersQueryOptions(groupId), - select: (data) => - data.members.find((m) => m.identity.identityId === identityId), - }); -}; diff --git a/frontend/apps/hub/src/domains/group/views/group-detailed-members.tsx b/frontend/apps/hub/src/domains/group/views/group-detailed-members.tsx deleted file mode 100644 index 1a9efd34b1..0000000000 --- a/frontend/apps/hub/src/domains/group/views/group-detailed-members.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import { groupMembersQueryOptions } from "@/domains/group/queries"; -import { groupOnwerQueryOptions } from "@/domains/project/queries"; -import { useDialog } from "@/hooks/use-dialog"; -import { - Button, - Card, - CardContent, - CardHeader, - CardTitle, - Flex, - Grid, - Text, -} from "@rivet-gg/components"; -import { Icon, faCrown } from "@rivet-gg/icons"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { Link } from "@tanstack/react-router"; -import { UserAvatar } from "../../user/components/user-avatar"; -import { GroupMemberSettingsMenu } from "../components/group-member-settings-menu"; - -interface GroupDetailedMembersProps { - groupId: string; -} - -export function GroupDetailedMembers({ groupId }: GroupDetailedMembersProps) { - const { data: groupOwnerIdentityId } = useSuspenseQuery( - groupOnwerQueryOptions(groupId), - ); - const { data } = useSuspenseQuery(groupMembersQueryOptions(groupId)); - - const { - open: confirmTransferOwnership, - dialog: confirmTransferOwnershipDialog, - } = useDialog.ConfirmTransferOwnership({ groupId }); - - const { open: confirmMemberKick, dialog: confirmMemberKickDialog } = - useDialog.ConfirmMemberKick({ groupId }); - - const { open: confirmMemberBan, dialog: confirmMemberBanDialog } = - useDialog.ConfirmMemberBan({ groupId }); - - return ( - - - - Members - - - - - {confirmTransferOwnershipDialog} - {confirmMemberKickDialog} - {confirmMemberBanDialog} - - {data.members.map((member) => ( - - - - - {member.identity.displayName} - {groupOwnerIdentityId === - member.identity.identityId && ( - - )} - - - - - ))} - - - - ); -} diff --git a/frontend/apps/hub/src/domains/group/views/group-list-view.tsx b/frontend/apps/hub/src/domains/group/views/group-list-view.tsx deleted file mode 100644 index 2ac7565b90..0000000000 --- a/frontend/apps/hub/src/domains/group/views/group-list-view.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { projectsByGroupQueryOptions } from "@/domains/project/queries"; -import { Flex } from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { Group } from "../components/group"; -import { GroupCreateCard } from "../components/group-create-card"; -import { NoGroupsAlert } from "../components/no-groups-alert"; - -export function GroupListView() { - const { data } = useSuspenseQuery(projectsByGroupQueryOptions()); - return ( - - {data.length === 0 ? ( - - ) : ( - <> - {data.map((group) => ( - - ))} - - - )} - - ); -} - -GroupListView.Skeleton = () => { - return ( - - - - - - ); -}; diff --git a/frontend/apps/hub/src/domains/group/views/group-members.tsx b/frontend/apps/hub/src/domains/group/views/group-members.tsx deleted file mode 100644 index 6474471c4e..0000000000 --- a/frontend/apps/hub/src/domains/group/views/group-members.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import { groupMembersQueryOptions } from "@/domains/group/queries"; -import { groupOnwerQueryOptions } from "@/domains/project/queries"; -import { - Button, - Card, - CardContent, - CardHeader, - CardTitle, - Flex, - Grid, - Text, -} from "@rivet-gg/components"; -import { Icon, faCrown, faRightFromBracket } from "@rivet-gg/icons"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { Link } from "@tanstack/react-router"; -import { UserAvatar } from "../../user/components/user-avatar"; - -interface GroupMembersProps { - groupId: string; -} - -export function GroupMembers({ groupId }: GroupMembersProps) { - const { data: groupOwnerIdentityId } = useSuspenseQuery( - groupOnwerQueryOptions(groupId), - ); - const { data } = useSuspenseQuery(groupMembersQueryOptions(groupId)); - - return ( - - - - Members - - - - - - - - - {data.members.map((member) => ( - - - - {member.identity.displayName} - {groupOwnerIdentityId === - member.identity.identityId && ( - - )} - - - ))} - - - - ); -} diff --git a/frontend/apps/hub/src/domains/group/views/group-projects.tsx b/frontend/apps/hub/src/domains/group/views/group-projects.tsx deleted file mode 100644 index d459614ff8..0000000000 --- a/frontend/apps/hub/src/domains/group/views/group-projects.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import { BillingPlanBadge } from "@/domains/project/components/billing/billing-plan-badge"; -import { ProjectTableActions } from "@/domains/project/components/project-table-actions"; -import { groupProjectsQueryOptions } from "@/domains/project/queries"; -import { - Button, - Card, - CardContent, - CardHeader, - CardTitle, - Flex, - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, - Text, -} from "@rivet-gg/components"; -import { Icon, faPlus } from "@rivet-gg/icons"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { Link, useNavigate } from "@tanstack/react-router"; - -interface GroupProjectsProps { - groupId: string; -} - -export function GroupProjects({ groupId }: GroupProjectsProps) { - const { data } = useSuspenseQuery(groupProjectsQueryOptions(groupId)); - - const navigate = useNavigate(); - - return ( - <> - - - - Projects - - - - - - - - - - Name - - - - - {data.projects.length === 0 ? ( - - - - There's no projects yet. - - - - ) : null} - {data.projects.map((project) => ( - { - navigate({ - to: "/projects/$projectNameId", - params: { - projectNameId: project.nameId, - }, - }); - }} - > - - - - {project.displayName}{" "} - - - - - - - - - ))} - -
-
-
- - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/actors/actors-actor-details-wrapper.tsx b/frontend/apps/hub/src/domains/project/components/actors/actors-actor-details-wrapper.tsx deleted file mode 100644 index c05228ec7c..0000000000 --- a/frontend/apps/hub/src/domains/project/components/actors/actors-actor-details-wrapper.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { ActorsActorDetails } from "@rivet-gg/components/actors"; -import type { ActorAtom } from "@rivet-gg/components/actors"; -import { useEnvironment } from "../../data/environment-context"; -import { useProject } from "../../data/project-context"; -import { useExportActorLogsMutation } from "../../queries/actors/mutations"; - -interface ActorsActorDetailsWrapperProps { - tab?: string; - actor: ActorAtom; - onTabChange?: (tab: string) => void; -} - -export function ActorsActorDetailsWrapper({ - tab, - actor, - onTabChange, -}: ActorsActorDetailsWrapperProps) { - const { nameId: projectNameId } = useProject(); - const { nameId: environmentNameId } = useEnvironment(); - const exportMutation = useExportActorLogsMutation(); - - const handleExportLogs = async ( - actorId: string, - _typeFilter?: string, - _filter?: string, - ) => { - // TODO: Add above filters - const result = await exportMutation.mutateAsync({ - projectNameId, - environmentNameId, - queryJson: JSON.stringify({ - string_equal: { - property: "actor_id", - value: actorId, - }, - }), - }); - - // Open the presigned URL in a new tab to download - window.open(result.url, "_blank"); - }; - - return ( - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/actors/actors-provider.tsx b/frontend/apps/hub/src/domains/project/components/actors/actors-provider.tsx deleted file mode 100644 index 1049551360..0000000000 --- a/frontend/apps/hub/src/domains/project/components/actors/actors-provider.tsx +++ /dev/null @@ -1,582 +0,0 @@ -import { router } from "@/app"; -import { queryClient } from "@/queries/global"; -import type { Rivet } from "@rivet-gg/api-full"; -import { type FilterValue, toRecord } from "@rivet-gg/components"; -import { - type Actor, - type DestroyActor, - type Logs, - type Metrics, - actorBuildsAtom, - actorEnvironmentAtom, - actorFiltersAtom, - actorRegionsAtom, - actorsAtom, - actorsInternalFilterAtom, - actorsPaginationAtom, - actorsQueryAtom, - createActorAtom, - currentActorIdAtom, - currentActorQueryAtom, - getActorStatus, -} from "@rivet-gg/components/actors"; -import { - InfiniteQueryObserver, - InfiniteQueryObserverSuccessResult, - MutationObserver, - QueryObserver, -} from "@tanstack/react-query"; -import equal from "fast-deep-equal"; -//import { createClient } from "actor-core/client"; -import { type PrimitiveAtom, Provider, atom, createStore } from "jotai"; -import { type ReactNode, useEffect, useState } from "react"; -import { - actorBuildsQueryOptions, - actorLogsQueryOptions, - actorMetricsQueryOptions, - actorQueryOptions, - actorRegionsQueryOptions, - createActorEndpoint, - destroyActorMutationOptions, - projectActorsQueryOptions, -} from "../../queries"; - -interface ActorsProviderProps { - actorId: string | undefined; - projectNameId: string; - environmentNameId: string; - children?: ReactNode; - fixedTags?: Record; - filter?: (actor: Rivet.actors.Actor) => boolean; - isActorInternal?: (actor: Actor) => boolean; - - /// filters - tags: FilterValue; - region: FilterValue; - createdAt: FilterValue; - destroyedAt: FilterValue; - status: FilterValue; - devMode: FilterValue; -} - -function mountActor({ - actor, - projectNameId, - environmentNameId, -}: { - actor: Rivet.actors.Actor; - projectNameId: string; - environmentNameId: string; -}) { - const destroy: PrimitiveAtom = atom({ - isDestroying: false as boolean, - destroy: async () => {}, - }); - destroy.onMount = (set) => { - const mutObserver = new MutationObserver( - queryClient, - destroyActorMutationOptions(), - ); - - set({ - destroy: async () => { - await mutObserver.mutate({ - projectNameId, - environmentNameId, - actorId: actor.id, - }); - }, - isDestroying: false, - }); - - mutObserver.subscribe((mutation) => { - set({ - destroy: async () => { - await mutation.mutate({ - projectNameId, - environmentNameId, - actorId: actor.id, - }); - }, - isDestroying: mutation.isPending, - }); - }); - - return () => { - mutObserver.reset(); - }; - }; - - const logs = atom({ - logs: [] as Logs, - status: "pending", - }); - logs.onMount = (set) => { - const logsObserver = new QueryObserver( - queryClient, - actorLogsQueryOptions({ - projectNameId, - environmentNameId, - actorId: actor.id, - }), - ); - - type LogQuery = { - status: string; - data?: Awaited< - ReturnType< - Exclude< - ReturnType["queryFn"], - undefined - > - > - >; - }; - - function updateStdOut(query: LogQuery) { - const data = query.data; - set((prev) => ({ - ...prev, - ...data, - status: query.status, - })); - } - - const subOut = logsObserver.subscribe((query) => { - updateStdOut(query); - }); - - updateStdOut(logsObserver.getCurrentQuery().state); - - return () => { - logsObserver.destroy(); - subOut(); - }; - }; - - const metrics = atom({ - metrics: { cpu: null, memory: null } as Metrics, - updatedAt: Date.now(), - status: "pending", - }); - metrics.onMount = (set) => { - const metricsObserver = new QueryObserver( - queryClient, - actorMetricsQueryOptions( - { - projectNameId, - environmentNameId, - actorId: actor.id, - }, - { refetchInterval: 5000 }, - ), - ); - - type MetricsQuery = { - status: string; - data?: Awaited< - ReturnType< - Exclude< - ReturnType["queryFn"], - undefined - > - > - >; - }; - - function updateMetrics(query: MetricsQuery) { - const data = query.data; - set((prev) => ({ - ...prev, - ...data, - status: query.status, - updatedAt: Date.now(), - })); - } - - const subMetrics = metricsObserver.subscribe((query) => { - updateMetrics(query); - }); - - updateMetrics(metricsObserver.getCurrentQuery().state); - - return () => { - metricsObserver.destroy(); - subMetrics(); - }; - }; - - return { - ...actor, - logs, - metrics, - destroy, - status: getActorStatus(actor), - }; -} - -export function ActorsProvider({ - actorId, - projectNameId, - environmentNameId, - children, - fixedTags, - filter, - isActorInternal: internalFilter, - // filters - tags, - region, - createdAt, - destroyedAt, - status, - devMode, -}: ActorsProviderProps) { - const [store] = useState(() => createStore()); - - // biome-ignore lint/correctness/useExhaustiveDependencies: store is not a dependency - useEffect(() => { - store.set(currentActorIdAtom, actorId); - store.set(currentActorQueryAtom, { isLoading: false, error: null }); - if (!actorId) { - return; - } - - const actor = store.get(actorsAtom).find((a) => a.id === actorId); - if (actor) { - return; - } - - store.set(currentActorQueryAtom, { isLoading: true, error: null }); - const observer = new QueryObserver( - queryClient, - actorQueryOptions({ - actorId, - projectNameId, - environmentNameId, - }), - ); - - return observer.subscribe((query) => { - store.set(currentActorQueryAtom, { - isLoading: query.isLoading, - error: query.error, - }); - if (query.status === "success" && query.data) { - store.set(actorsAtom, (actors) => { - const existing = actors.find((a) => a.id === actorId); - - if (existing) { - return actors.map((a) => - a.id === actorId - ? { - ...existing, - ...query.data, - status: getActorStatus(query.data), - endpoint: createActorEndpoint( - query.data.network, - ), - tags: toRecord(existing.tags), - } - : a, - ); - } - - return [ - ...actors, - mountActor({ - actor: query.data, - projectNameId, - environmentNameId, - }), - ]; - }); - } - }); - }, [actorId]); - - // biome-ignore lint/correctness/useExhaustiveDependencies: store is not a dependency - useEffect(() => { - store.set(actorEnvironmentAtom, { projectNameId, environmentNameId }); - }, [projectNameId, environmentNameId]); - - // biome-ignore lint/correctness/useExhaustiveDependencies: store is not a dependency - useEffect(() => { - store.set(actorFiltersAtom, { - tags, - region, - createdAt, - destroyedAt, - status, - devMode, - }); - }, [tags, region, createdAt, destroyedAt, status, devMode]); - - // biome-ignore lint/correctness/useExhaustiveDependencies: store is not a dependency - useEffect(() => { - if (internalFilter) { - store.set(actorsInternalFilterAtom, { fn: internalFilter }); - } else { - store.set(actorsInternalFilterAtom, undefined); - } - }, [internalFilter]); - - // biome-ignore lint/correctness/useExhaustiveDependencies: store is not a dependency - useEffect(() => { - return store.sub(actorFiltersAtom, () => { - const value = store.get(actorFiltersAtom); - router.navigate({ - to: ".", - search: (old) => ({ - ...old, - ...value, - }), - }); - }); - }, [router]); - - // biome-ignore lint/correctness/useExhaustiveDependencies: store is not a dependency - useEffect(() => { - const actorsObserver = new InfiniteQueryObserver( - queryClient, - projectActorsQueryOptions({ - projectNameId, - environmentNameId, - includeDestroyed: true, - tags: fixedTags, - }), - ); - - const unsubFilters = store.sub(actorFiltersAtom, () => { - actorsObserver.setOptions( - projectActorsQueryOptions({ - projectNameId, - environmentNameId, - tags: fixedTags, - includeDestroyed: true, - }), - ); - actorsObserver.refetch(); - }); - - const unsub = actorsObserver.subscribe((query) => { - store.set(actorsQueryAtom, { - isLoading: query.isLoading, - error: query.error?.message ?? null, - }); - store.set(actorsPaginationAtom, { - hasNextPage: query.hasNextPage, - fetchNextPage: () => query.fetchNextPage(), - isFetchingNextPage: query.isFetchingNextPage, - }); - if ( - query.status === "success" && - query.data && - !query.isPlaceholderData - ) { - store.set(actorsAtom, (actors) => { - const additionalActors = upsertCurrentActor({ - store, - query, - actors, - projectNameId, - environmentNameId, - }); - - return [ - ...additionalActors, - ...query.data - .filter((actor) => filter?.(actor) ?? true) - .map((actor) => { - const existing = actors.find( - (a) => a.id === actor.id, - ); - if (existing) { - return { - ...existing, - ...actor, - status: getActorStatus(actor), - endpoint: createActorEndpoint( - actor.network, - ), - tags: toRecord(existing.tags), - }; - } - - return mountActor({ - actor, - projectNameId, - environmentNameId, - }); - }), - ]; - }); - } - }); - return () => { - actorsObserver.destroy(); - unsub(); - unsubFilters(); - }; - }, [projectNameId, environmentNameId]); - - // biome-ignore lint/correctness/useExhaustiveDependencies: store is not a dependency - useEffect(() => { - const regionsObserver = new QueryObserver( - queryClient, - actorRegionsQueryOptions({ projectNameId, environmentNameId }), - ); - - const unsub = regionsObserver.subscribe((query) => { - if (query.status === "success" && query.data) { - store.set(actorRegionsAtom, query.data); - } - }); - - return () => { - regionsObserver.destroy(); - unsub(); - }; - }, [projectNameId, environmentNameId]); - - // biome-ignore lint/correctness/useExhaustiveDependencies: store is not a dependency - useEffect(() => { - const buildsObserver = new QueryObserver( - queryClient, - actorBuildsQueryOptions({ - projectNameId, - environmentNameId, - }), - ); - const unsub = buildsObserver.subscribe((query) => { - if (query.status === "success" && query.data) { - store.set(actorBuildsAtom, (old) => { - if (equal(old, query.data)) { - return old; - } - return query.data; - }); - } - }); - return () => { - buildsObserver.destroy(); - unsub(); - }; - }, [projectNameId, environmentNameId]); - - useEffect(() => { - const mutationObserver = new MutationObserver(queryClient, { - mutationFn: (data: { - endpoint: string; - id: string; - tags: Record; - region?: string; - params?: Record; - }) => { - //const client = createClient(data.endpoint); - // - //const build = store - // .get(actorBuildsAtom) - // .find((build) => build.id === data.id); - // - //return client.create(build?.tags.name || "", { - // params: data.params, - // create: { - // tags: data.tags, - // region: data.region || undefined, - // }, - //}); - }, - }); - - const storeSub = store.sub(actorsAtom, () => { - const manager = store - .get(actorsAtom) - .find( - (a) => - toRecord(a.tags).name === "manager" && - a.status === "running", - ); - - store.set(createActorAtom, (old) => { - return { - ...old, - endpoint: manager?.network - ? createActorEndpoint(manager.network) || null - : null, - }; - }); - }); - - store.set(createActorAtom, (old) => ({ - ...old, - create: mutationObserver.mutate, - })); - - const unsub = mutationObserver.subscribe((mutation) => { - store.set(createActorAtom, (old) => ({ - ...old, - isCreating: mutation.isPending, - create: mutation.mutate, - })); - }); - return () => { - unsub(); - storeSub(); - }; - }); - - return {children}; -} - -function upsertCurrentActor({ - store, - query, - actors, - projectNameId, - environmentNameId, -}: { - store: ReturnType; - query: InfiniteQueryObserverSuccessResult; - actors: Actor[]; - projectNameId: string; - environmentNameId: string; - additionalActors?: Actor[]; -}) { - // check if current actor is in the query data - const currentActorId = store.get(currentActorIdAtom); - if (currentActorId) { - // if there's no current actor in the query data, we upsert it from the query data - const currentActor = query.data.find((a) => a.id === currentActorId); - if (currentActor) { - // it will be mounted in the next pass - return []; - } - - // check if it's not already in the actors list - const existing = actors.find((a) => a.id === currentActorId); - if (existing) { - // if not, we add it to the additional actors - return [existing]; - } - - // as a last resort, check the query data for the current actor - const actorQuery = queryClient.getQueryData( - actorQueryOptions({ - actorId: currentActorId, - projectNameId, - environmentNameId, - }).queryKey, - ); - - if (actorQuery) { - return [ - mountActor({ - actor: actorQuery, - projectNameId, - environmentNameId, - }), - ]; - } - } - return []; -} diff --git a/frontend/apps/hub/src/domains/project/components/backend/backend-deployment-link.tsx b/frontend/apps/hub/src/domains/project/components/backend/backend-deployment-link.tsx deleted file mode 100644 index 5ed6a48d2c..0000000000 --- a/frontend/apps/hub/src/domains/project/components/backend/backend-deployment-link.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { Link } from "@rivet-gg/components"; - -interface BackendDeploymentLinkProps { - url: string; -} - -export function BackendDeploymentLink({ url }: BackendDeploymentLinkProps) { - return ( - - {url} - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/backend/backend-environment-database-link.tsx b/frontend/apps/hub/src/domains/project/components/backend/backend-environment-database-link.tsx deleted file mode 100644 index 8e9464e9f0..0000000000 --- a/frontend/apps/hub/src/domains/project/components/backend/backend-environment-database-link.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { Slot } from "@radix-ui/react-slot"; -import { Button, type ButtonProps } from "@rivet-gg/components"; -import { Icon, faDatabase, faExternalLink } from "@rivet-gg/icons"; -import { useNavigate } from "@tanstack/react-router"; -import { type ReactNode, forwardRef } from "react"; -import { useEnvironmentDatabasePreview } from "../../queries"; - -interface BackendEnvironmentDatabaseLinkProps - extends Omit { - projectId: string; - environmentId: string; - asChild?: boolean; - children?: ReactNode; -} - -export const BackendEnvironmentDatabaseLink = forwardRef< - HTMLButtonElement, - BackendEnvironmentDatabaseLinkProps ->(({ projectId, environmentId, asChild, children, ...props }, ref) => { - const { isLoading, data } = useEnvironmentDatabasePreview({ - projectId, - environmentId, - }); - - const C = asChild ? Slot : Button; - const navigate = useNavigate(); - - return ( - { - e?.preventDefault(); - if (isLoading) { - return; - } - if (!data) { - return navigate({ to: ".", search: { modal: "database" } }); - } - if (typeof data === "string") { - window.open(data, "_blank", "noreferrer,noopener"); - } - }} - isLoading={isLoading} - startIcon={} - endIcon={ - data ? ( - - ) : undefined - } - {...props} - > - {children} - - ); -}); diff --git a/frontend/apps/hub/src/domains/project/components/backend/backend-environment-table-actions.tsx b/frontend/apps/hub/src/domains/project/components/backend/backend-environment-table-actions.tsx deleted file mode 100644 index 0b564e6f4d..0000000000 --- a/frontend/apps/hub/src/domains/project/components/backend/backend-environment-table-actions.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { - Button, - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from "@rivet-gg/components"; -import { Icon, faEllipsisH } from "@rivet-gg/icons"; - -export function BackendEnvironmentTableActions() { - return ( - - - - - - Manage - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/backend/backend-event-details-panel.tsx b/frontend/apps/hub/src/domains/project/components/backend/backend-event-details-panel.tsx deleted file mode 100644 index 301a0f69c5..0000000000 --- a/frontend/apps/hub/src/domains/project/components/backend/backend-event-details-panel.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { Flex, Text } from "@rivet-gg/components"; -import { BackendEventDetails } from "./backend-event-details"; - -interface BackendEventDetailsPanelProps { - environmentId: string; - projectId: string; - eventId: string | undefined; -} - -export function BackendEventDetailsPanel({ - eventId, - projectId, - environmentId, -}: BackendEventDetailsPanelProps) { - if (!eventId) { - return ( - - - Please select an event from the list on the left. - - - ); - } - return ( - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/backend/backend-event-details.tsx b/frontend/apps/hub/src/domains/project/components/backend/backend-event-details.tsx deleted file mode 100644 index 92edf2a123..0000000000 --- a/frontend/apps/hub/src/domains/project/components/backend/backend-event-details.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { - Badge, - CopyArea, - Flex, - Tabs, - TabsContent, - TabsList, - TabsTrigger, - Text, -} from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { projectBackendEnvEventQueryOptions } from "../../queries"; -import { BackendEventDetailsHeadersTab } from "./backend-event-details/backend-event-details-headers-tab"; -import { BackendEventDetailsLogsTab } from "./backend-event-details/backend-event-details-logs-tab"; -import { BackendEventDetailsWipTab } from "./backend-event-details/backend-event-details-wip-tab"; -import { BackendResponseBadge } from "./backend-response-badge"; - -interface BackendEventDetailsProps { - eventId: string; - projectId: string; - environmentId: string; -} - -export function BackendEventDetails({ - eventId, - projectId, - environmentId, -}: BackendEventDetailsProps) { - const { data } = useSuspenseQuery( - projectBackendEnvEventQueryOptions({ - eventId, - projectId, - environmentId, - }), - ); - - if (!data) { - return ( - - - No event found. - - - ); - } - - return ( - -
- - @ {data.eventDate} -
- -
-
- - - Logs - Headers - Request - Response - - - - - - - - - - - - - - -
- ); -} diff --git a/frontend/apps/hub/src/domains/project/components/backend/backend-event-details/backend-event-details-headers-tab.tsx b/frontend/apps/hub/src/domains/project/components/backend/backend-event-details/backend-event-details-headers-tab.tsx deleted file mode 100644 index 2fe6057a6e..0000000000 --- a/frontend/apps/hub/src/domains/project/components/backend/backend-event-details/backend-event-details-headers-tab.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import type { BackendEvent } from "@/domains/project/queries"; -import { CopyArea, Grid, ScrollArea } from "@rivet-gg/components"; -import { Fragment } from "react/jsx-runtime"; - -interface BackendEventDetailsHeadersProps { - event: BackendEvent["event"]; -} - -export function BackendEventDetailsHeadersTab({ - event, -}: BackendEventDetailsHeadersProps) { - return ( - - - {Object.entries(event.request.headers).map(([name, value]) => ( - - - - - ))} - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/backend/backend-event-details/backend-event-details-logs-tab.tsx b/frontend/apps/hub/src/domains/project/components/backend/backend-event-details/backend-event-details-logs-tab.tsx deleted file mode 100644 index e476012d27..0000000000 --- a/frontend/apps/hub/src/domains/project/components/backend/backend-event-details/backend-event-details-logs-tab.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { Button, LogsView, WithTooltip } from "@rivet-gg/components"; -import { Icon, faSave } from "@rivet-gg/icons"; -import saveAs from "file-saver"; -import type { BackendEvent } from "../../../queries"; - -interface BackendEventDetailsLogsTabProps - extends Pick {} - -export function BackendEventDetailsLogsTab({ - logs, - logTimestamps, -}: BackendEventDetailsLogsTabProps) { - return ( -
- No logs available.

} - sidebar={ - - saveAs( - new Blob( - [ - logs - .map((line) => line.message) - .join("\n"), - ], - { - type: "text/plain;charset=utf-8", - }, - ), - "logs.txt", - ) - } - > - - - } - /> - } - /> -
- ); -} diff --git a/frontend/apps/hub/src/domains/project/components/backend/backend-event-details/backend-event-details-wip-tab.tsx b/frontend/apps/hub/src/domains/project/components/backend/backend-event-details/backend-event-details-wip-tab.tsx deleted file mode 100644 index a78c14d691..0000000000 --- a/frontend/apps/hub/src/domains/project/components/backend/backend-event-details/backend-event-details-wip-tab.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { Text } from "@rivet-gg/components"; - -export function BackendEventDetailsWipTab() { - return ( -
- Not implemented yet. -
- ); -} diff --git a/frontend/apps/hub/src/domains/project/components/backend/backend-events-list-panel.tsx b/frontend/apps/hub/src/domains/project/components/backend/backend-events-list-panel.tsx deleted file mode 100644 index b000460057..0000000000 --- a/frontend/apps/hub/src/domains/project/components/backend/backend-events-list-panel.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { - Button, - Flex, - ScrollArea, - SmallText, - Uptime, - WithTooltip, -} from "@rivet-gg/components"; -import { Link } from "@tanstack/react-router"; -import type { BackendEvent } from "../../queries"; -import { BackendResponseBadge } from "./backend-response-badge"; - -interface BackendEventsListPanelProps { - events: BackendEvent[]; - eventId: string | undefined; -} - -export function BackendEventsListPanel({ - eventId, - events, -}: BackendEventsListPanelProps) { - return ( - - - {events.map((event) => ( - - ))} - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/backend/backend-list-events-preview.tsx b/frontend/apps/hub/src/domains/project/components/backend/backend-list-events-preview.tsx deleted file mode 100644 index 41a564c9da..0000000000 --- a/frontend/apps/hub/src/domains/project/components/backend/backend-list-events-preview.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { - ResizableHandle, - ResizablePanel, - ResizablePanelGroup, - Text, - useBreakpoint, -} from "@rivet-gg/components"; -import type { BackendEvent } from "../../queries"; -import { BackendEventDetailsPanel } from "./backend-event-details-panel"; -import { BackendEventsListPanel } from "./backend-events-list-panel"; - -interface BackendListEventsPreviewProps { - events: BackendEvent[]; - environmentId: string; - projectId: string; - eventId?: string; -} - -export function BackendListEventsPreview({ - events, - eventId, - projectId, - environmentId, -}: BackendListEventsPreviewProps) { - if (events.length === 0) { - return ( - - No events found. - - ); - } - - const isMd = useBreakpoint("md"); - - return ( - - -
- -
-
- - -
- -
-
-
- ); -} diff --git a/frontend/apps/hub/src/domains/project/components/backend/backend-response-badge.tsx b/frontend/apps/hub/src/domains/project/components/backend/backend-response-badge.tsx deleted file mode 100644 index 94c0e23389..0000000000 --- a/frontend/apps/hub/src/domains/project/components/backend/backend-response-badge.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { Badge } from "@rivet-gg/components"; -import type { BackendEvent } from "../../queries"; - -const getResponseType = (event: BackendEvent["event"]) => { - if (event.response.status >= 300 && event.response.status < 400) { - return "warning"; - } - if (event.response.status >= 400) { - return "error"; - } - return "success"; -}; - -const getResponseTypeVariant = (type: "warning" | "error" | "success") => { - if (type === "warning") { - return "warning"; - } - if (type === "error") { - return "destructive-muted"; - } - return "outline"; -}; - -const getResponseLabel = (outcome: string, type: string) => { - if (outcome.startsWith("exceeded")) { - return "TIMEOUT"; - } - if (outcome === "canceled") { - return "CANCELED"; - } - if (type === "error") { - return "ERROR"; - } - return "OK"; -}; - -interface BackendResponseBadgeProps extends BackendEvent {} - -export function BackendResponseBadge({ - backendCall, - event, - outcome, -}: BackendResponseBadgeProps) { - const type = getResponseType(event); - const variant = getResponseTypeVariant(type); - - const label = getResponseLabel(outcome, type); - - if (backendCall) { - return ( - <> - CALL - {label} - - ); - } - return ( - <> - HTTP - - {event.response.status} {label} - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/billing/billing-context.tsx b/frontend/apps/hub/src/domains/project/components/billing/billing-context.tsx deleted file mode 100644 index c2550da7a3..0000000000 --- a/frontend/apps/hub/src/domains/project/components/billing/billing-context.tsx +++ /dev/null @@ -1,133 +0,0 @@ -import type { Rivet as RivetEe } from "@rivet-gg/api-ee"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { type ReactNode, createContext, useContext } from "react"; - -import { clusterQueryOptions } from "@/domains/auth/queries/bootstrap"; -import type { Rivet } from "@rivet-gg/api-full"; -import { startOfMonth } from "date-fns"; -import { calculateUsedCredits } from "../../data/billing-calculate-usage"; -import { useProject } from "../../data/project-context"; -import { - projectBillingQueryOptions, - projectBillingUsageQueryOptions, - projectQueryOptions, -} from "../../queries"; - -interface BillingContextValue { - project: Rivet.cloud.GameFull; - activePlan: RivetEe.ee.billing.Plan; - plan: RivetEe.ee.billing.Plan; - credits: { - max: number; - used: number; - overage: number; - remaining: number; - total: number; - }; - subscription: RivetEe.ee.billing.Subscription | undefined; -} - -export const BillingContext = createContext( - undefined, -); - -interface BillingSubscriptionProviderProps { - project: Rivet.cloud.GameFull; - subscription: RivetEe.ee.billing.Subscription | undefined; - plan: RivetEe.ee.billing.Plan; - activePlan: RivetEe.ee.billing.Plan; - children?: ReactNode; -} - -const today = new Date(); -const firstDayOfMonth = startOfMonth(today); - -function BillingSubscriptionProvider({ - children, - ...rest -}: BillingSubscriptionProviderProps) { - const { - project: { gameId, developerGroupId }, - subscription, - activePlan, - plan, - } = rest; - const { data: usage } = useSuspenseQuery( - projectBillingUsageQueryOptions({ - projectId: gameId, - groupId: developerGroupId, - startTs: subscription?.periodStartTs || firstDayOfMonth, - endTs: subscription?.periodEndTs || today, - }), - ); - - const credits = calculateUsedCredits({ usage, plan: activePlan }); - - return ( - - {children} - - ); -} - -interface BillingProviderContentProps { - projectId: string; - groupId: string; - children?: ReactNode; -} -function Content({ - projectId, - groupId, - children, -}: BillingProviderContentProps) { - const { data: project } = useSuspenseQuery(projectQueryOptions(projectId)); - const { data } = useSuspenseQuery(projectBillingQueryOptions(projectId)); - - if (data) { - return ( - - {children} - - ); - } - return children; -} - -interface BillingProviderProps { - children?: ReactNode; -} - -export const BillingProvider = ({ children }: BillingProviderProps) => { - const { - gameId: projectId, - developer: { groupId }, - } = useProject(); - - const { data } = useSuspenseQuery(clusterQueryOptions()); - - if (data === "oss") { - return children; - } - - return ( - - {children} - - ); -}; - -export const useBilling = () => { - const context = useContext(BillingContext); - if (!context) { - throw new Error("useBilling must be used within a BillingProvider"); - } - return context; -}; - -export const useOptionalBilling = () => { - return useContext(BillingContext); -}; diff --git a/frontend/apps/hub/src/domains/project/components/billing/billing-header.tsx b/frontend/apps/hub/src/domains/project/components/billing/billing-header.tsx deleted file mode 100644 index 1a2ac310e9..0000000000 --- a/frontend/apps/hub/src/domains/project/components/billing/billing-header.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { Flex, H1 } from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import type { ReactNode } from "react"; -import { projectQueryOptions } from "../../queries"; - -interface BillingHeaderProps { - projectId: string; - lead?: ReactNode; - actions?: ReactNode; -} - -export function BillingHeader({ - projectId, - actions, - lead, -}: BillingHeaderProps) { - const { - data: { displayName }, - } = useSuspenseQuery(projectQueryOptions(projectId)); - - return ( - - -

{displayName} Billing

- {lead} -
- {actions ? {actions} : null} -
- ); -} diff --git a/frontend/apps/hub/src/domains/project/components/billing/billing-missing-payment-method.tsx b/frontend/apps/hub/src/domains/project/components/billing/billing-missing-payment-method.tsx deleted file mode 100644 index 71ca66b15c..0000000000 --- a/frontend/apps/hub/src/domains/project/components/billing/billing-missing-payment-method.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { - Alert, - AlertDescription, - AlertTitle, - Flex, -} from "@rivet-gg/components"; -import { Icon, faCreditCard } from "@rivet-gg/icons"; -import { BillingHeader } from "./billing-header"; -import { BillingPortalButton } from "./billing-portal-button"; - -interface MissingPaymentMethodProps { - groupId: string; - projectId: string; -} - -export function MissingPaymentMethod({ - groupId, - projectId, -}: MissingPaymentMethodProps) { - return ( - <> - - - - Heads up! - - - You must add a payment method before you can add servers - to your project. - - Add payment method - - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/billing/billing-overage-warning.tsx b/frontend/apps/hub/src/domains/project/components/billing/billing-overage-warning.tsx deleted file mode 100644 index 066bc193d3..0000000000 --- a/frontend/apps/hub/src/domains/project/components/billing/billing-overage-warning.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { Alert, AlertTitle, Button, Flex } from "@rivet-gg/components"; -import { Icon, faExclamationTriangle } from "@rivet-gg/icons"; -import { Link } from "@tanstack/react-router"; -import { BILLING_PLANS_CREDITS_VISIBILITY } from "../../data/billing-calculate-usage"; -import { useOptionalBilling } from "./billing-context"; - -export function BillingOverageWarning() { - const billing = useOptionalBilling(); - - if (!billing) { - return null; - } - - const { - project: { nameId: projectNameId }, - activePlan, - credits: { overage }, - } = billing; - - if ( - overage <= 0 || - !BILLING_PLANS_CREDITS_VISIBILITY.includes(activePlan) - ) { - return null; - } - - return ( - - - - - You have exceeded your credit limit for this billing period. -
- Please upgrade your plan to avoid service interruption. -
- -
-
- ); -} diff --git a/frontend/apps/hub/src/domains/project/components/billing/billing-plan-badge.tsx b/frontend/apps/hub/src/domains/project/components/billing/billing-plan-badge.tsx deleted file mode 100644 index da6adb26e1..0000000000 --- a/frontend/apps/hub/src/domains/project/components/billing/billing-plan-badge.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { clusterQueryOptions } from "@/domains/auth/queries/bootstrap"; -import { Rivet } from "@rivet-gg/api-ee"; -import { Badge, Skeleton } from "@rivet-gg/components"; -import { useQuery, useSuspenseQuery } from "@tanstack/react-query"; -import { useIntersectionObserver } from "usehooks-ts"; -import { projectBillingQueryOptions } from "../../queries"; - -const BILLING_PLAN_LABELS = { - [Rivet.ee.billing.Plan.Indie]: "Pro", - [Rivet.ee.billing.Plan.Studio]: "Team", - [Rivet.ee.billing.Plan.Trial]: "Free", -}; - -const BILLING_PLAN_COLORS = { - [Rivet.ee.billing.Plan.Indie]: "default", - [Rivet.ee.billing.Plan.Studio]: "default", - [Rivet.ee.billing.Plan.Trial]: "secondary", -} as const; - -interface BillingPlanBadgeProps { - projectId: string; -} - -function Content({ projectId }: BillingPlanBadgeProps) { - const { ref, isIntersecting } = useIntersectionObserver({ - root: null, - rootMargin: "0px", - threshold: [1], - }); - - const { data, isSuccess } = useQuery( - projectBillingQueryOptions(projectId, { - enabled: isIntersecting ?? false, - }), - ); - - if (!data?.plan) { - return null; - } - - if (isSuccess) { - return ( - - - - ); - } - - return ; -} - -export function BillingPlanBadge({ projectId }: BillingPlanBadgeProps) { - const { data } = useSuspenseQuery(clusterQueryOptions()); - - if (data === "oss") { - return null; - } - - return ; -} - -export function ProjectBillingPlanLabel({ - plan, -}: { plan: Rivet.ee.billing.Plan }) { - return BILLING_PLAN_LABELS[plan]; -} diff --git a/frontend/apps/hub/src/domains/project/components/billing/billing-plan-card.tsx b/frontend/apps/hub/src/domains/project/components/billing/billing-plan-card.tsx deleted file mode 100644 index 229a77bbfa..0000000000 --- a/frontend/apps/hub/src/domains/project/components/billing/billing-plan-card.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import { - Button, - Card, - CardContent, - CardFooter, - CardHeader, - Flex, - SmallText, - Text, - cn, -} from "@rivet-gg/components"; -import { Icon, type IconProp } from "@rivet-gg/icons"; -import type { ReactNode } from "@tanstack/react-router"; - -export interface BillingPlanCardProps { - title: string; - lead?: string; - price: string; - priceLead?: string; - features: { - key?: string; - name: ReactNode; - icon?: IconProp; - bold?: boolean; - }[]; - type?: "custom" | "active"; - onSubscribe?: () => void; - onCancel?: () => void; - cancelLabel?: string; -} - -export function BillingPlanCard({ - title, - lead, - price, - priceLead, - type, - features, - cancelLabel, - onSubscribe, - onCancel, -}: BillingPlanCardProps) { - return ( - - - {title} - {lead ? {lead} : null} -
-

- - {price} - - - {type !== "custom" ? "/mo" : null} - -

- {priceLead ? ( - - {priceLead} - - ) : null} -
-
- - -
    - {features.map(({ key, name, bold, icon }) => ( - -
  • - {icon ? ( - - ) : null} - {name} -
  • -
    - ))} -
-
-
- - {type === "custom" ? ( - - - - ) : null} - {type === "active" && onCancel ? ( - - ) : null} - {!type ? : null} - -
- ); -} diff --git a/frontend/apps/hub/src/domains/project/components/billing/billing-plan-period.tsx b/frontend/apps/hub/src/domains/project/components/billing/billing-plan-period.tsx deleted file mode 100644 index c62efe9d63..0000000000 --- a/frontend/apps/hub/src/domains/project/components/billing/billing-plan-period.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { format } from "date-fns"; -import { useBilling } from "./billing-context"; - -export function BillingPlanPeriod() { - const { subscription } = useBilling(); - - if (!subscription) { - return null; - } - - return ( -

- Billing period: {format(subscription.periodStartTs, "MMMM do")} -{" "} - {format(subscription.periodEndTs, "MMMM do")} -

- ); -} diff --git a/frontend/apps/hub/src/domains/project/components/billing/billing-plan-status.tsx b/frontend/apps/hub/src/domains/project/components/billing/billing-plan-status.tsx deleted file mode 100644 index 3d509fc6b8..0000000000 --- a/frontend/apps/hub/src/domains/project/components/billing/billing-plan-status.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { Rivet } from "@rivet-gg/api-ee"; -import { SmallText } from "@rivet-gg/components"; -import { format } from "date-fns"; -import { useBilling } from "./billing-context"; -import { ProjectBillingPlanLabel } from "./billing-plan-badge"; - -export function BillingPlanStatus() { - const { activePlan, plan, subscription } = useBilling(); - - if (!subscription) { - return null; - } - - if ( - activePlan === Rivet.ee.billing.Plan.Trial && - plan === Rivet.ee.billing.Plan.Trial - ) { - return null; - } - - if (activePlan === plan) { - return ( - - Renews on {format(subscription.periodEndTs, "MMMM do")} - - ); - } - - if (activePlan !== plan) { - return ( - - Downgrades from to{" "} - on{" "} - {format(subscription.periodEndTs, "MMMM do")} - - ); - } -} diff --git a/frontend/apps/hub/src/domains/project/components/billing/billing-plans.tsx b/frontend/apps/hub/src/domains/project/components/billing/billing-plans.tsx deleted file mode 100644 index d13f3aa5af..0000000000 --- a/frontend/apps/hub/src/domains/project/components/billing/billing-plans.tsx +++ /dev/null @@ -1,225 +0,0 @@ -import { useDialog } from "@/hooks/use-dialog"; -import { Rivet as RivetEe } from "@rivet-gg/api-ee"; -import { Flex, Grid, H2, Link } from "@rivet-gg/components"; -import { - faBadgeCheck, - faCheckCircle, - faClock, - faComments, - faDatabase, - faEnvelope, - faGift, - faGlobe, - faHeadset, - faInfinity, - faLockA, - faPeopleGroup, - faRocketLaunch, - faServer, -} from "@rivet-gg/icons"; -import { PRICE_MAP } from "../../data/billing-calculate-usage"; -import { useBilling } from "./billing-context"; -import { - BillingPlanCard, - type BillingPlanCardProps, -} from "./billing-plan-card"; -import { BillingPlanStatus } from "./billing-plan-status"; - -interface BillingPlansProps { - projectId: string; - showHeader?: boolean; - onChoosePlan?: () => Promise | void; - config?: Partial< - Record> - >; -} - -export function BillingPlans({ - projectId, - onChoosePlan, - showHeader = true, - config, -}: BillingPlansProps) { - const { dialog, open } = useDialog.ConfirmBillingPlan({ - projectId, - onSuccess: onChoosePlan, - }); - - const { plan } = useBilling(); - - return ( - <> - {showHeader ? ( - -

Plan

- -
- ) : null} - {dialog} - - - open({ - plan: RivetEe.ee.billing.Plan.Trial, - }) - } - onCancel={onChoosePlan} - type={ - plan === RivetEe.ee.billing.Plan.Trial - ? "active" - : undefined - } - features={[ - { - name: ( - - $5.00 Free - - /mo - - - ), - bold: true, - icon: faGift, - }, - { name: "Community Support", icon: faComments }, - ]} - {...config?.[RivetEe.ee.billing.Plan.Trial]} - /> - - open({ - plan: RivetEe.ee.billing.Plan.Indie, - }) - } - onCancel={() => - open({ - plan: RivetEe.ee.billing.Plan.Trial, - }) - } - price={`$${PRICE_MAP[RivetEe.ee.billing.Plan.Indie]}`} - type={ - plan === RivetEe.ee.billing.Plan.Indie - ? "active" - : undefined - } - priceLead="+ Actor Usage" - features={[ - { - name: ( - - $20 Free - - /mo - - - ), - bold: true, - icon: faGift, - }, - { - name: "Everything in Community", - icon: faCheckCircle, - }, - { name: "No Usage Limits", icon: faInfinity }, - - { name: "Unlimited Seats", icon: faPeopleGroup }, - { name: "Email Support", icon: faEnvelope }, - ]} - {...config?.[RivetEe.ee.billing.Plan.Indie]} - /> - - open({ - plan: RivetEe.ee.billing.Plan.Studio, - }) - } - onCancel={() => - open({ - plan: RivetEe.ee.billing.Plan.Trial, - }) - } - price={`$${PRICE_MAP[RivetEe.ee.billing.Plan.Studio]}`} - type={ - plan === RivetEe.ee.billing.Plan.Studio - ? "active" - : undefined - } - priceLead="+ Actor Usage" - features={[ - { - name: ( - - $200 Free - - /mo - - - ), - bold: true, - icon: faGift, - }, - { name: "Everything in Pro", icon: faCheckCircle }, - { - name: "Dedicated Hardware", - icon: faServer, - }, - { name: "Custom Regions", icon: faGlobe }, - { name: "Advanced Support", icon: faHeadset }, - ]} - {...config?.[RivetEe.ee.billing.Plan.Studio]} - /> - - - -

- Read more about our plans and see comparison table on our{" "} - - pricing page - - . -

- - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/billing/billing-portal-button.tsx b/frontend/apps/hub/src/domains/project/components/billing/billing-portal-button.tsx deleted file mode 100644 index 4a437d6fe7..0000000000 --- a/frontend/apps/hub/src/domains/project/components/billing/billing-portal-button.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { Button, type ButtonProps } from "@rivet-gg/components"; -import { useQuery } from "@tanstack/react-query"; -import { portalBillingSessionQueryOptions } from "../../queries"; - -interface BillingPortalButtonProps extends ButtonProps { - groupId: string; - intent: "general" | "payment_method_update"; -} - -export function BillingPortalButton({ - groupId, - intent, - ...props -}: BillingPortalButtonProps) { - const { data, isLoading } = useQuery( - portalBillingSessionQueryOptions(groupId, intent), - ); - - return ( - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/billing/billing-summary.tsx b/frontend/apps/hub/src/domains/project/components/billing/billing-summary.tsx deleted file mode 100644 index df63804c00..0000000000 --- a/frontend/apps/hub/src/domains/project/components/billing/billing-summary.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { AnimatedCurrency, Grid, ValueCard } from "@rivet-gg/components"; -import { useBilling } from "./billing-context"; - -export function BillingSummary() { - const { - credits: { total, remaining }, - } = useBilling(); - - return ( - - } - /> - } - /> - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/billing/billing-usage-progress.tsx b/frontend/apps/hub/src/domains/project/components/billing/billing-usage-progress.tsx deleted file mode 100644 index 215605b541..0000000000 --- a/frontend/apps/hub/src/domains/project/components/billing/billing-usage-progress.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { Rivet as RivetEe } from "@rivet-gg/api-ee"; -import { - Alert, - AlertTitle, - Flex, - RangedProgressBar, - Text, - formatCurrency, -} from "@rivet-gg/components"; -import { Icon, faExclamationTriangle } from "@rivet-gg/icons"; -import { BILLING_PLANS_CREDITS_VISIBILITY as BILLING_PLANS_OVERAGE_ALERT_VISIBILITY } from "../../data/billing-calculate-usage"; - -// Use a number below 100 to left some space for the overage -const MAX_RANGE = 75; - -interface CommonUsageProgressProps { - plan: RivetEe.ee.billing.Plan; -} - -interface FreeUsageProgressProps { - isFree: true; -} - -interface PaidUsageProgressProps { - isFree?: false; - max: number; - used: number; - overage: number; -} - -type BillingUsageProgressProps = CommonUsageProgressProps & - (FreeUsageProgressProps | PaidUsageProgressProps); - -export function BillingUsageProgress(props: BillingUsageProgressProps) { - if (props.isFree) { - return ( - - Free while in Beta - - ); - } - - const { used, max, overage, plan } = props; - const percentage = Math.min((used / max) * MAX_RANGE, MAX_RANGE); - - return ( - <> - {overage > 0 && - BILLING_PLANS_OVERAGE_ALERT_VISIBILITY.includes(plan) ? ( - - - - You have exceeded the billing credits limit! - - - ) : null} - - - Usage -
- {formatCurrency(used)} - - } - maxLabel={ - <> - {plan === RivetEe.ee.billing.Plan.Trial - ? "Free tier limit" - : "Included credits"} -
- {formatCurrency(max)} - - } - /> -
-

Month-to-date

-

- {formatCurrency(overage)} -

-
-
- - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/billing/billing-usage.tsx b/frontend/apps/hub/src/domains/project/components/billing/billing-usage.tsx deleted file mode 100644 index c5b8e7cbba..0000000000 --- a/frontend/apps/hub/src/domains/project/components/billing/billing-usage.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { - Card, - CardContent, - CardHeader, - CardTitle, - H2, -} from "@rivet-gg/components"; -import { useBilling } from "./billing-context"; -import { BillingUsageProgress } from "./billing-usage-progress"; - -export function BillingUsage() { - const { - activePlan, - credits: { max, used, overage }, - } = useBilling(); - - return ( - <> -

Usage

- - - Dynamic Servers - - - - - - - - Backend (Database) - - - - - - - - Backend (Modules) - - - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/billing/billing.tsx b/frontend/apps/hub/src/domains/project/components/billing/billing.tsx deleted file mode 100644 index b891b02ce9..0000000000 --- a/frontend/apps/hub/src/domains/project/components/billing/billing.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { Icon, faExternalLink } from "@rivet-gg/icons"; -import { BillingHeader } from "./billing-header"; -import { BillingPlanPeriod } from "./billing-plan-period"; -import { BillingPlans } from "./billing-plans"; -import { BillingPortalButton } from "./billing-portal-button"; - -interface BillingProps { - projectId: string; - groupId: string; -} -export function Billing({ projectId, groupId }: BillingProps) { - return ( - <> - } - actions={ - <> - } - > - Invoices - - } - > - Payment Method - - - } - /> - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/billing/charts/usage-chart.tsx b/frontend/apps/hub/src/domains/project/components/billing/charts/usage-chart.tsx deleted file mode 100644 index 63de4a4e17..0000000000 --- a/frontend/apps/hub/src/domains/project/components/billing/charts/usage-chart.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { useId } from "react"; -import { - Area, - AreaChart, - CartesianGrid, - ResponsiveContainer, - Tooltip, - XAxis, - YAxis, -} from "recharts"; - -export function UsageChart() { - const id = useId(); - return ( - - - - - - - - - - - - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/build-select.tsx b/frontend/apps/hub/src/domains/project/components/build-select.tsx deleted file mode 100644 index 7566ef37ae..0000000000 --- a/frontend/apps/hub/src/domains/project/components/build-select.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { Combobox } from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { actorBuildsQueryOptions } from "../queries"; - -interface BuildSelectProps { - projectNameId: string; - environmentNameId: string; - onValueChange: (value: string) => void; - value: string; -} - -export function BuildSelect({ - projectNameId, - environmentNameId, - onValueChange, - value, -}: BuildSelectProps) { - const { data } = useSuspenseQuery( - actorBuildsQueryOptions({ - projectNameId, - environmentNameId, - tags: { current: "true" }, - }), - ); - - const builds = data - .toSorted((a, b) => b.createdAt.valueOf() - a.createdAt.valueOf()) - .map((build) => { - return { - label: ( -
-
-
- {build.tags.name || build.id.split("-")[0]} -
-
- Created: {build.createdAt.toLocaleString()} -
-
-
- ), - value: build.id, - build, - }; - }); - - return ( - - option.build.id.includes(search) || - option.build.name.includes(search) - } - className="w-full h-14" - /> - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/dialogs/cdn-manage-auth-users-dialog.tsx b/frontend/apps/hub/src/domains/project/components/dialogs/cdn-manage-auth-users-dialog.tsx deleted file mode 100644 index 21a9f56728..0000000000 --- a/frontend/apps/hub/src/domains/project/components/dialogs/cdn-manage-auth-users-dialog.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import * as CdnManageAuthUsersForm from "@/domains/project/forms/cdn-manage-auth-users-form"; -import type { DialogContentProps } from "@/hooks/use-dialog"; -import { - DialogFooter, - DialogHeader, - DialogTitle, - Flex, - Text, -} from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { useCdnManageAuthUsersFormHandler } from "../../hooks/use-cdn-manage-auth-users-form-handler"; -import { projectEnvironmentQueryOptions } from "../../queries"; - -interface ContentProps extends DialogContentProps { - projectId: string; - environmentId: string; -} - -export default function CdnManageAuthUsersDialogContent({ - projectId, - environmentId, - onClose, -}: ContentProps) { - const { data } = useSuspenseQuery( - projectEnvironmentQueryOptions({ projectId, environmentId }), - ); - - const handleSubmit = useCdnManageAuthUsersFormHandler({ - environmentId, - projectId, - onSuccess: onClose, - userList: data.namespace.config.cdn.authUserList, - }); - - return ( - ({ - ...user, - password: "", - })), - }} - > - - Manage CDN Authentication Users - - - - Once this page is refreshed, none of the entered passwords - will show up here. You can edit the password for any given - user by inputting a new one. - - - - - - Save - - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/dialogs/cdn-manage-custom-domains-dialog.tsx b/frontend/apps/hub/src/domains/project/components/dialogs/cdn-manage-custom-domains-dialog.tsx deleted file mode 100644 index cdb4611402..0000000000 --- a/frontend/apps/hub/src/domains/project/components/dialogs/cdn-manage-custom-domains-dialog.tsx +++ /dev/null @@ -1,165 +0,0 @@ -import * as CdnNewCustomDomainForm from "@/domains/project/forms/cdn-new-custom-domain-form"; -import type { DialogContentProps } from "@/hooks/use-dialog"; -import { Rivet } from "@rivet-gg/api-full"; -import { - Badge, - Button, - DialogFooter, - DialogHeader, - DialogTitle, - Flex, - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, - WithTooltip, -} from "@rivet-gg/components"; -import { Icon, faInfoCircle, faPlus, faTrash } from "@rivet-gg/icons"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { useCdnNewCustomDomainFormHandler } from "../../hooks/use-cdn-new-custom-domain-form-handler"; -import { - projectEnvironmentQueryOptions, - useEnvironmentRemoveDomainMutation, -} from "../../queries"; - -const VARIANT_MAP = { - [Rivet.cloud.CdnNamespaceDomainVerificationStatus.Active]: null, - [Rivet.cloud.CdnNamespaceDomainVerificationStatus.Pending]: - "secondary" as const, - [Rivet.cloud.CdnNamespaceDomainVerificationStatus.Failed]: - "destructive" as const, -}; - -interface DomainConfigRowProps extends Rivet.cloud.CdnNamespaceDomain { - projectId: string; - environmentId: string; -} - -function DomainConfigRow({ - domain, - createTs, - verificationErrors, - verificationStatus, - projectId, - environmentId, -}: DomainConfigRowProps) { - const { mutate: removeDomain, isPending } = - useEnvironmentRemoveDomainMutation(); - - return ( - - {domain} - {createTs.toLocaleString()} - - {verificationErrors[0] ? ( - - {verificationStatus} - - - } - /> - ) : ( - - {verificationStatus} - - )} - - - - - - ); -} - -interface ContentProps extends DialogContentProps { - projectId: string; - environmentId: string; -} - -export default function CdnManageCustomDomainsDialogContent({ - projectId, - environmentId, - onClose, -}: ContentProps) { - const { data, refetch, isRefetching } = useSuspenseQuery( - projectEnvironmentQueryOptions({ projectId, environmentId }), - ); - - const handleSubmit = useCdnNewCustomDomainFormHandler({ - environmentId, - projectId, - }); - - return ( - <> - - Manage CDN Custom Domains - - - - - - - - - - - - - Name - Created - Status - - - - - {data.namespace.config.cdn.domains.map((domainConfig) => ( - - ))} - -
- - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/dialogs/confirm-billing-plan-dialog.tsx b/frontend/apps/hub/src/domains/project/components/dialogs/confirm-billing-plan-dialog.tsx deleted file mode 100644 index f10b2ea3ac..0000000000 --- a/frontend/apps/hub/src/domains/project/components/dialogs/confirm-billing-plan-dialog.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import type { DialogContentProps } from "@/hooks/use-dialog"; -import type { Rivet } from "@rivet-gg/api-ee"; -import { - Button, - DialogFooter, - DialogHeader, - DialogTitle, - Flex, - Text, -} from "@rivet-gg/components"; -import { useUpdateProjectBillingMutation } from "../../queries"; -import { ProjectBillingPlanLabel } from "../billing/billing-plan-badge"; - -interface ContentProps extends DialogContentProps { - plan: Rivet.ee.billing.Plan; - projectId: string; - onSuccess?: () => void; -} - -export default function ConfirmBillingPlanDialogContent({ - plan, - projectId, - onSuccess, - onClose, -}: ContentProps) { - const { mutate, isPending } = useUpdateProjectBillingMutation({ - onSuccess: async () => { - await onSuccess?.(); - onClose?.(); - }, - }); - - return ( - <> - - Confirm Billing Plan Change - - - - Are you sure you want to change your current plan to{" "} - ? - - - - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/dialogs/confirm-outerbase-connection-dialog.tsx b/frontend/apps/hub/src/domains/project/components/dialogs/confirm-outerbase-connection-dialog.tsx deleted file mode 100644 index 1ff9671a92..0000000000 --- a/frontend/apps/hub/src/domains/project/components/dialogs/confirm-outerbase-connection-dialog.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import type { DialogContentProps } from "@/hooks/use-dialog"; -import { - Button, - DialogFooter, - DialogHeader, - DialogTitle, - Flex, - Link, - Text, -} from "@rivet-gg/components"; -import { Icon, faExternalLink } from "@rivet-gg/icons"; -import { useProjectBackendEnvDatabasePreviewMutation } from "../../queries"; - -interface ContentProps extends DialogContentProps { - projectId: string; - environmentId: string; -} - -export default function ConfirmOuterbaseConnectionDialogContent({ - projectId, - environmentId, - onClose, -}: ContentProps) { - const { isPending, mutate } = useProjectBackendEnvDatabasePreviewMutation({ - onSuccess: (url) => { - window.open(url, "_blank", "noreferrer,noopener"); - onClose?.(); - }, - }); - - return ( - <> - - Connect Rivet to Outerbase - - - - This will give Outerbase credentials to your database. Read - more about Outerbase security{" "} - - here - - . - - - - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/dialogs/create-environment-dialog.tsx b/frontend/apps/hub/src/domains/project/components/dialogs/create-environment-dialog.tsx deleted file mode 100644 index 5d547d2a22..0000000000 --- a/frontend/apps/hub/src/domains/project/components/dialogs/create-environment-dialog.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import * as EnvironmentCreateForm from "@/domains/project/forms/environment-create-form"; -import type { DialogContentProps } from "@/hooks/use-dialog"; -import { convertStringToId } from "@/lib/utils"; -import { - DialogFooter, - DialogHeader, - DialogTitle, - Flex, -} from "@rivet-gg/components"; -import { useQueryClient, useSuspenseQuery } from "@tanstack/react-query"; -import { useNavigate } from "@tanstack/react-router"; -import { - projectEnvironmentQueryOptions, - projectQueryOptions, - useEnvironmentCreateMutation, -} from "../../queries"; - -interface ContentProps extends DialogContentProps { - projectId: string; -} - -export default function CreateEnvironmentDialogContent({ - projectId, -}: ContentProps) { - const queryClient = useQueryClient(); - const navigate = useNavigate(); - const { data: project } = useSuspenseQuery(projectQueryOptions(projectId)); - const { mutateAsync } = useEnvironmentCreateMutation({ - onSuccess: async (data) => { - const env = await queryClient.ensureQueryData( - projectEnvironmentQueryOptions({ - projectId, - environmentId: data.namespaceId, - }), - ); - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId", - params: { - projectNameId: project.nameId, - environmentNameId: env.namespace.nameId, - }, - }); - }, - }); - - return ( - <> - { - await mutateAsync({ - projectId, - displayName: values.name, - nameId: values.slug || convertStringToId(values.name), - versionId: project.versions[0].versionId, - }); - }} - defaultValues={{ name: "", slug: "", projectId }} - > - - Create New Environment - - - - - - - - Create - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/dialogs/create-project-dialog.tsx b/frontend/apps/hub/src/domains/project/components/dialogs/create-project-dialog.tsx deleted file mode 100644 index 04a30ca4c1..0000000000 --- a/frontend/apps/hub/src/domains/project/components/dialogs/create-project-dialog.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import * as ProjectCreateForm from "@/domains/project/forms/create-project-form"; -import { convertStringToId } from "@/lib/utils"; -import type { Rivet } from "@rivet-gg/api-full"; -import { - DialogFooter, - DialogHeader, - DialogTitle, - Flex, -} from "@rivet-gg/components"; -import { useProjectCreateMutation } from "../../queries"; - -interface CreateProjectDialogContentProps { - groupId?: string; - onSuccess?: (data: Rivet.cloud.GameFull) => void; -} - -export default function CreateProjectDialogContent({ - onSuccess, - groupId = "", -}: CreateProjectDialogContentProps) { - const { mutateAsync } = useProjectCreateMutation({ - onSuccess, - }); - - return ( - <> - { - await mutateAsync({ - developerGroupId, - displayName: name, - nameId: slug || convertStringToId(name), - }); - }} - defaultValues={{ - name: "", - slug: "", - developerGroupId: groupId, - }} - > - - Create New Project - - - - - - - - - Create - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/dialogs/create-route-dialog.tsx b/frontend/apps/hub/src/domains/project/components/dialogs/create-route-dialog.tsx deleted file mode 100644 index c4bfd5328e..0000000000 --- a/frontend/apps/hub/src/domains/project/components/dialogs/create-route-dialog.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import * as EditRouteForm from "@/domains/project/forms/route-edit-form"; -import type { DialogContentProps } from "@/hooks/use-dialog"; -import { - Button, - DialogFooter, - DialogHeader, - DialogTitle, - Label, -} from "@rivet-gg/components"; -import { useState } from "react"; -import { useCreateRouteMutation } from "../../queries"; - -interface ContentProps extends DialogContentProps { - projectNameId: string; - environmentNameId: string; -} - -export default function CreateRouteDialogContent(props: ContentProps) { - return ; -} - -function Content({ projectNameId, environmentNameId, onClose }: ContentProps) { - const { mutateAsync } = useCreateRouteMutation(); - - const [tagKeys, setTagKeys] = useState<{ label: string; value: string }[]>( - () => [], - ); - - const [tagValues, setTagValues] = useState< - { label: string; value: string }[] - >(() => []); - - return ( - { - const selectorTags = Object.fromEntries( - values.tags.map(({ key, value }) => [key, value]), - ); - - await mutateAsync({ - projectNameId, - environmentNameId, - hostname: values.hostname, - path: values.path, - stripPrefix: values.stripPrefix || false, - routeSubpaths: values.routeSubpaths || false, - target: { - actors: { - selectorTags, - }, - }, - }); - onClose?.(); - }} - > - - Add Route - -
- - -
- - - - - setTagKeys((opts) => [ - ...opts, - { label: option, value: option }, - ]) - } - onCreateValueOption={(option) => - setTagValues((opts) => [ - ...opts, - { label: option, value: option }, - ]) - } - /> - - - - - - Save - - -
- ); -} diff --git a/frontend/apps/hub/src/domains/project/components/dialogs/deploy-environment-version-dialog.tsx b/frontend/apps/hub/src/domains/project/components/dialogs/deploy-environment-version-dialog.tsx deleted file mode 100644 index 3c4977521f..0000000000 --- a/frontend/apps/hub/src/domains/project/components/dialogs/deploy-environment-version-dialog.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import type { DialogContentProps } from "@/hooks/use-dialog"; -import { - Button, - DialogFooter, - DialogHeader, - DialogTitle, - Flex, - Strong, - Text, -} from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { - projectQueryOptions, - useUpdateProjectEnvironmentVersionMutation, -} from "../../queries"; - -interface ContentProps extends DialogContentProps { - projectId: string; - environmentId: string; - versionId: string; -} - -export default function DeployEnvironmentVersionDialogContent({ - projectId, - environmentId, - versionId, - onClose, -}: ContentProps) { - const { data: project } = useSuspenseQuery(projectQueryOptions(projectId)); - const { mutate, isPending } = useUpdateProjectEnvironmentVersionMutation({ - onSuccess: onClose, - }); - - const chosenVersion = project.versions.find( - (v) => v.versionId === versionId, - ); - const chosenEnvironment = project.namespaces.find( - (ns) => ns.namespaceId === environmentId, - ); - return ( - <> - - - Deploy version {chosenVersion?.displayName} to{" "} - {chosenEnvironment?.displayName} of {project.displayName} - - - - - Are you sure you want to deploy version{" "} - {chosenVersion?.displayName} created at{" "} - {chosenVersion?.createTs.toLocaleString()} to environment{" "} - {chosenEnvironment?.displayName} of project{" "} - {project.displayName}? - - - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/dialogs/edit-build-tags-dialog.tsx b/frontend/apps/hub/src/domains/project/components/dialogs/edit-build-tags-dialog.tsx deleted file mode 100644 index cef69afbf2..0000000000 --- a/frontend/apps/hub/src/domains/project/components/dialogs/edit-build-tags-dialog.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import * as EditBuildTagsForm from "@/domains/project/forms/build-tags-form"; -import type { DialogContentProps } from "@/hooks/use-dialog"; -import { - Button, - DialogFooter, - DialogHeader, - DialogTitle, -} from "@rivet-gg/components"; -import { useSuspenseQueries } from "@tanstack/react-query"; -import { useState } from "react"; -import { - actorBuildQueryOptions, - actorBuildsQueryOptions, - usePatchActorBuildTagsMutation, -} from "../../queries"; - -interface ContentProps extends DialogContentProps { - projectNameId: string; - environmentNameId: string; - buildId: string; -} - -export default function EditBuildTagsDialogContent(props: ContentProps) { - if (!props.buildId) { - return null; - } - - return ; -} - -function Content({ - buildId, - projectNameId, - environmentNameId, - onClose, -}: ContentProps) { - const [{ data }, { data: builds }] = useSuspenseQueries({ - queries: [ - actorBuildQueryOptions({ - buildId, - projectNameId, - environmentNameId, - }), - actorBuildsQueryOptions({ projectNameId, environmentNameId }), - ], - }); - const { mutateAsync } = usePatchActorBuildTagsMutation(); - - const [tagKeys, setTagKeys] = useState(() => - Array.from( - new Set( - builds?.flatMap((build) => Object.keys(build.tags)), - ).values(), - ).map((key) => ({ - label: key, - value: key, - })), - ); - - const [tagValues, setTagValues] = useState(() => - Array.from( - new Set( - builds?.flatMap((build) => Object.values(build.tags)), - ).values(), - ).map((key) => ({ label: key, value: key })), - ); - - return ( - ({ - key, - value, - })), - }} - onSubmit={async (values) => { - const tags = Object.fromEntries( - values.tags.map(({ key, value }) => [key, value]), - ); - - await mutateAsync({ - projectNameId, - environmentNameId, - buildId, - tags, - }); - onClose?.(); - }} - > - - Edit Build Tags - - - - setTagKeys((opts) => [ - ...opts, - { label: option, value: option }, - ]) - } - onCreateValueOption={(option) => - setTagValues((opts) => [ - ...opts, - { label: option, value: option }, - ]) - } - /> - - - Save - - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/dialogs/edit-route-dialog.tsx b/frontend/apps/hub/src/domains/project/components/dialogs/edit-route-dialog.tsx deleted file mode 100644 index ad7393e8a1..0000000000 --- a/frontend/apps/hub/src/domains/project/components/dialogs/edit-route-dialog.tsx +++ /dev/null @@ -1,179 +0,0 @@ -import * as EditRouteForm from "@/domains/project/forms/route-edit-form"; -import type { DialogContentProps } from "@/hooks/use-dialog"; -import type { Rivet } from "@rivet-gg/api-full"; -import { - Button, - DialogFooter, - DialogHeader, - DialogTitle, - Label, -} from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { useState } from "react"; -import { routeQueryOptions, usePatchRouteMutation } from "../../queries"; - -interface OptionalContentProps extends DialogContentProps { - projectNameId: string; - environmentNameId: string; - routeId?: string; -} - -export default function EditRouteDialogContent(props: OptionalContentProps) { - if (!props.routeId) { - return null; - } - - return ; -} - -function GuardedContent({ - routeId, - projectNameId, - environmentNameId, - onClose, -}: Omit & { routeId: string }) { - const { data } = useSuspenseQuery( - routeQueryOptions({ - routeId, - projectNameId, - environmentNameId, - }), - ); - - if (!data) { - return ( - <> -
-

Route not found

-

- The route you are trying to edit does not exist. -

-
- - - - - - ); - } - - return ( - - ); -} - -interface ContentProps extends DialogContentProps, Rivet.routes.Route { - projectNameId: string; - environmentNameId: string; -} - -function Content({ - projectNameId, - id, - target, - environmentNameId, - hostname, - routeSubpaths, - stripPrefix, - path, - onClose, -}: ContentProps) { - const { mutateAsync } = usePatchRouteMutation(); - - const tags = Object.entries(target?.actors?.selectorTags || {}).map( - ([key, value]) => ({ - key, - value, - }), - ); - - const [tagKeys, setTagKeys] = useState<{ label: string; value: string }[]>( - () => tags.map(({ key }) => ({ label: key, value: key })), - ); - - const [tagValues, setTagValues] = useState< - { label: string; value: string }[] - >(() => tags.map(({ value }) => ({ label: value, value }))); - - return ( - ({ - key, - value, - }), - ), - hostname, - path, - routeSubpaths, - stripPrefix, - }} - onSubmit={async (values) => { - const selectorTags = Object.fromEntries( - values.tags.map(({ key, value }) => [key, value]), - ); - - await mutateAsync({ - projectNameId, - environmentNameId, - id, - hostname: values.hostname, - path: values.path, - stripPrefix: values.stripPrefix || false, - routeSubpaths: values.routeSubpaths || false, - target: { - actors: { - selectorTags, - }, - }, - }); - onClose?.(); - }} - > - - Add Route - -
- - -
- - - - - setTagKeys((opts) => [ - ...opts, - { label: option, value: option }, - ]) - } - onCreateValueOption={(option) => - setTagValues((opts) => [ - ...opts, - { label: option, value: option }, - ]) - } - /> - - - - - - Save - - -
- ); -} diff --git a/frontend/apps/hub/src/domains/project/components/dialogs/environment-generate-public-token-dialog.tsx b/frontend/apps/hub/src/domains/project/components/dialogs/environment-generate-public-token-dialog.tsx deleted file mode 100644 index f859e55137..0000000000 --- a/frontend/apps/hub/src/domains/project/components/dialogs/environment-generate-public-token-dialog.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import type { DialogContentProps } from "@/hooks/use-dialog"; -import { - Button, - CopyArea, - DialogFooter, - DialogHeader, - DialogTitle, - Flex, - Text, -} from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { projectEnvironmentTokenPublicQueryOptions } from "../../queries"; - -interface ContentProps extends DialogContentProps { - projectId: string; - environmentId: string; -} - -export default function EnvironmentGeneratePublicTokenDialogContent({ - projectId, - environmentId, - onClose, -}: ContentProps) { - const { data } = useSuspenseQuery( - projectEnvironmentTokenPublicQueryOptions({ projectId, environmentId }), - ); - return ( - <> - - Create Environment Public Token - - - - Copy this token to your clipboard. You will not be able to - access this token again. - - - - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/dialogs/environment-generate-service-token-dialog.tsx b/frontend/apps/hub/src/domains/project/components/dialogs/environment-generate-service-token-dialog.tsx deleted file mode 100644 index ea072b195b..0000000000 --- a/frontend/apps/hub/src/domains/project/components/dialogs/environment-generate-service-token-dialog.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import type { DialogContentProps } from "@/hooks/use-dialog"; -import { - Button, - CopyArea, - DialogFooter, - DialogHeader, - DialogTitle, - Flex, - Text, -} from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { projectEnvTokenServiceQueryOptions } from "../../queries"; - -interface ContentProps extends DialogContentProps { - projectId: string; - environmentId: string; -} - -export default function ProjectEnvGenerateServiceTokenDialogContent({ - projectId, - environmentId, - onClose, -}: ContentProps) { - const { data } = useSuspenseQuery( - projectEnvTokenServiceQueryOptions({ projectId, environmentId }), - ); - return ( - <> - - Create Environment Service Token - - - - Copy this token to your clipboard. You will not be able to - access this token again. - - - - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/dialogs/group-create-project-dialog.tsx b/frontend/apps/hub/src/domains/project/components/dialogs/group-create-project-dialog.tsx deleted file mode 100644 index 2e51b63b35..0000000000 --- a/frontend/apps/hub/src/domains/project/components/dialogs/group-create-project-dialog.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import * as ProjectCreateForm from "@/domains/project/forms/group-create-project-form"; -import { convertStringToId } from "@/lib/utils"; -import { - DialogFooter, - DialogHeader, - DialogTitle, - Flex, -} from "@rivet-gg/components"; -import { useQueryClient } from "@tanstack/react-query"; -import { useNavigate } from "@tanstack/react-router"; -import { projectQueryOptions, useProjectCreateMutation } from "../../queries"; - -interface ContentProps { - groupId: string; -} - -export default function CreateGroupProjectDialogContent({ - groupId, -}: ContentProps) { - const queryClient = useQueryClient(); - const navigate = useNavigate(); - const { mutateAsync } = useProjectCreateMutation({ - onSuccess: async (data) => { - const project = await queryClient.ensureQueryData( - projectQueryOptions(data.gameId), - ); - navigate({ - to: "/projects/$projectNameId", - params: { projectNameId: project.game.nameId }, - }); - }, - }); - - return ( - <> - { - await mutateAsync({ - developerGroupId: groupId, - displayName: values.name, - nameId: values.slug || convertStringToId(values.name), - }); - }} - defaultValues={{ name: "", slug: "" }} - > - - Create New Project - - - - - - - - Create - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/dialogs/project-generate-cloud-token-dialog.tsx b/frontend/apps/hub/src/domains/project/components/dialogs/project-generate-cloud-token-dialog.tsx deleted file mode 100644 index 94fd192075..0000000000 --- a/frontend/apps/hub/src/domains/project/components/dialogs/project-generate-cloud-token-dialog.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import type { DialogContentProps } from "@/hooks/use-dialog"; -import { - Button, - CopyArea, - DialogFooter, - DialogHeader, - DialogTitle, - Flex, - Text, -} from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { projectTokenCloudQueryOptions } from "../../queries"; - -interface ContentProps extends DialogContentProps { - projectId: string; -} - -export default function ProjectGenerateCloudTokenDialogContent({ - projectId, - onClose, -}: ContentProps) { - const { data } = useSuspenseQuery( - projectTokenCloudQueryOptions({ projectId }), - ); - return ( - <> - - Create Project Cloud Token - - - - Copy this token to your clipboard. You will not be able to - access this token again. - - - - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-cpu-stats.tsx b/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-cpu-stats.tsx deleted file mode 100644 index 957c68c06b..0000000000 --- a/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-cpu-stats.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import type { Rivet } from "@rivet-gg/api-full"; -import { - type ChartConfig, - ChartContainer, - ChartTooltip, - ChartTooltipContent, - timing, -} from "@rivet-gg/components"; -import { format } from "date-fns"; -import { useId } from "react"; -import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from "recharts"; - -interface LobbyCPUStatsProps extends Pick { - metricsAt: number; - syncId?: string; -} - -const chartConfig = { - value: { - color: "hsl(var(--chart-1))", - label: "CPU Usage", - }, -} satisfies ChartConfig; - -export function LobbyCPUStats({ cpu, metricsAt, syncId }: LobbyCPUStatsProps) { - const data = cpu.map((value, i) => ({ - x: `${(cpu.length - i) * -15}`, - value: value / 100, - config: { - label: new Date(metricsAt - (cpu.length - i) * timing.seconds(15)), - }, - })); - - const id = useId(); - - const fillId = `fill-${id}`; - return ( - - - - - `${value * 100}%`} - /> - { - return format(label, "HH:mm:ss"); - }} - valueFormatter={(value) => { - if (typeof value !== "number") { - return "n/a"; - } - return `${(value * 100).toFixed(2)}%`; - }} - /> - } - /> - - - - - - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-lifecycle.tsx b/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-lifecycle.tsx deleted file mode 100644 index 70249029ff..0000000000 --- a/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-lifecycle.tsx +++ /dev/null @@ -1,13 +0,0 @@ -interface LobbyLifecycleProps { - createTs: Date; - readyTs?: Date; - stopTs?: Date; -} - -export function LobbyLifecycle({ - createTs, - readyTs, - stopTs, -}: LobbyLifecycleProps) { - return null; -} diff --git a/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-logs.tsx b/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-logs.tsx deleted file mode 100644 index f177c081ee..0000000000 --- a/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-logs.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import type { Rivet } from "@rivet-gg/api-full"; -import { Button, LogsView, WithTooltip } from "@rivet-gg/components"; -import { Icon, faSave } from "@rivet-gg/icons"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { - projectEnvironmentLogsLobbyLogsQueryOptions, - useExportLobbyLogsMutation, -} from "../../queries"; - -interface LobbyLogsProps { - projectId: string; - lobbyId: string; - isLive?: boolean; - logType: Rivet.cloud.games.LogStream; -} - -export function LobbyLogs({ - projectId, - lobbyId, - isLive, - logType, -}: LobbyLogsProps) { - const { - data: { timestamps, lines }, - } = useSuspenseQuery( - projectEnvironmentLogsLobbyLogsQueryOptions( - { - projectId, - lobbyId, - stream: logType, - }, - { refetchInterval: isLive ? 1000 : undefined }, - ), - ); - - const { mutate: download, isPending } = useExportLobbyLogsMutation(); - - return ( - - download({ - lobbyId, - projectId, - stream: logType, - }) - } - > - - - } - /> - } - /> - ); -} - -LobbyLogs.Skeleton = () => { - return ( -
- -
- ); -}; diff --git a/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-memory-stats.tsx b/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-memory-stats.tsx deleted file mode 100644 index 34da450b9f..0000000000 --- a/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-memory-stats.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import type { Rivet } from "@rivet-gg/api-full"; -import { - type ChartConfig, - ChartContainer, - ChartTooltip, - ChartTooltipContent, - timing, -} from "@rivet-gg/components"; -import { format } from "date-fns"; -import { filesize } from "filesize"; -import { useId } from "react"; -import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from "recharts"; - -interface LobbyMemoryStatsProps - extends Pick { - metricsAt: number; - syncId?: string; -} - -const chartConfig = { - value: { - color: "hsl(var(--chart-1))", - label: "Memory Usage", - }, -} satisfies ChartConfig; - -export function LobbyMemoryStats({ - memory, - allocatedMemory, - metricsAt, - syncId, -}: LobbyMemoryStatsProps) { - const data = memory.map((value, i) => ({ - x: `${(memory.length - i) * -15}`, - value, - config: { - label: new Date( - metricsAt - (memory.length - i) * timing.seconds(15), - ), - }, - })); - - const max = allocatedMemory || Math.max(...memory); - - const id = useId(); - - const fillId = `fill-${id}`; - return ( - - - - - - `${Math.ceil((value / max) * 100)}%` - } - /> - { - return format(label, "HH:mm:ss"); - }} - valueFormatter={(value) => { - if (typeof value !== "number") { - return "n/a"; - } - return `${filesize(value)} (${Math.round((value / max) * 100).toFixed(2)}%)`; - }} - /> - } - /> - - - - - - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-metrics.tsx b/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-metrics.tsx deleted file mode 100644 index 9f115542b1..0000000000 --- a/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-metrics.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import type { Rivet } from "@rivet-gg/api-full"; -import { Flex, Progress, SmallText, WithTooltip } from "@rivet-gg/components"; -import { filesize } from "filesize"; - -interface LobbyMetricsProps extends Rivet.cloud.SvcMetrics { - lobbyId: string; -} - -export function LobbyMetrics({ - allocatedMemory, - memory, - cpu, -}: LobbyMetricsProps) { - const currentMemory = memory[memory.length - 1]; - const memoryPercentage = (currentMemory / (allocatedMemory || 1)) * 100; - - const cpuPercentage = cpu[cpu.length - 1]; - const maxMemory = allocatedMemory || Math.max(...memory); - return ( - - - Memory - - - } - content={ - <> - {filesize(currentMemory)} / {filesize(maxMemory)} ( - {memoryPercentage.toFixed(2)}%) - - } - /> - - - CPU - - - } - content={<>{cpuPercentage.toFixed(2)}%} - /> - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-region.tsx b/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-region.tsx deleted file mode 100644 index b01a24931d..0000000000 --- a/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-region.tsx +++ /dev/null @@ -1,179 +0,0 @@ -import { converEmojiToUriFriendlyString } from "@/lib/emoji"; -import { AssetImage, Flex, WithTooltip } from "@rivet-gg/components"; -import { Icon, type IconProp, faComputer } from "@rivet-gg/icons"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { projectRegionQueryOptions } from "../../queries"; - -export const REGION_ICON: Record = { - local: faComputer, - unknown: "❓", - atlanta: "🇺🇸", // Atlanta - san_francisco: "🇺🇸", // San Francisco - frankfurt: "🇩🇪", // Frankfurt - sydney: "🇦🇺", // Sydney - tokyo: "🇯🇵", // Tokyo - mumbai: "🇮🇳", // Mumbai - toronto: "🇨🇦", // Toronto - washington_dc: "🇺🇸", // Washington DC - dallas: "🇺🇸", // Dallas - new_york_city: "🇺🇸", // Newark - london: "🇬🇧", // London - singapore: "🇸🇬", // Singapore - amsterdam: "🇳🇱", // Amsterdam - chicago: "🇺🇸", // Chicago - bangalore: "🇮🇳", // Bangalore - paris: "🇫🇷", // Paris - seattle: "🇺🇸", // Seattle - stockholm: "🇸🇪", // Stockholm - newark: "🇺🇸", // Newark - sao_paulo: "🇧🇷", // Sao Paulo - chennai: "🇮🇳", // Chennai - osaka: "🇯🇵", // Osaka - milan: "🇮🇹", // Milan - miami: "🇺🇸", // Miami - jakarta: "🇮🇩", // Jakarta - los_angeles: "🇺🇸", // Los Angeles - atl: "🇺🇸", // Atlanta - sfo: "🇺🇸", // San Francisco - fra: "🇩🇪", // Frankfurt - syd: "🇦🇺", // Sydney - tok: "🇯🇵", // Tokyo - mba: "🇮🇳", // Mumbai - tor: "🇨🇦", // Toronto - dca: "🇺🇸", // Washington DC - dfw: "🇺🇸", // Dallas - ewr: "🇺🇸", // Newark - lon: "🇬🇧", // London - sgp: "🇸🇬", // Singapore - lax: "🇺🇸", // Los Angeles - osa: "🇯🇵", // Osaka - gru: "🇧🇷", // Sao Paulo - bom: "🇮🇳", // Mumbai - sin: "🇸🇬", // Singapore -}; - -export const REGION_LABEL: Record = { - local: "Local", - unknown: "Unknown", - atlanta: "Atlanta, Georgia, USA", - san_francisco: "San Francisco", - frankfurt: "Frankfurt", - sydney: "Sydney", - tokyo: "Tokyo", - mumbai: "Mumbai", - toronto: "Toronto", - washington_dc: "Washington DC", - dallas: "Dallas", - new_york_city: "New York City", - london: "London", - singapore: "Singapore", - amsterdam: "Amsterdam", - chicago: "Chicago", - bangalore: "Bangalore", - paris: "Paris", - seattle: "Seattle", - stockholm: "Stockholm", - newark: "Newark", - sao_paulo: "Sao Paulo", - chennai: "Chennai", - osaka: "Osaka", - milan: "Milan", - miami: "Miami", - jakarta: "Jakarta", - los_angeles: "Los Angeles", - atl: "Atlanta, Georgia, USA", - sfo: "San Francisco, California, USA", - fra: "Frankfurt, Germany", - syd: "Sydney, Australia", - tok: "Tokyo, Japan", - mba: "Mumbai, India", - tor: "Toronto, Canada", - dca: "Washington DC, USA", - dfw: "Dallas, Texas, USA", - ewr: "Newark, New Jersey, USA", - lon: "London, UK", - sgp: "Singapore", - lax: "Los Angeles, California, USA", - osa: "Osaka, Japan", - gru: "Sao Paulo", - bom: "Mumbai, India", - sin: "Singapore", -}; - -interface LobbyRegionProps { - regionId: string; - projectId: string; - showLabel?: boolean | "abbreviated"; -} - -export function getRegionKey(regionNameId: string | undefined) { - // HACK: Remove prefix for old regions with format `lnd-atl` - const regionIdSplit = (regionNameId || "").split("-"); - return regionIdSplit[regionIdSplit.length - 1]; -} - -export function RegionIcon({ - region = "", - ...props -}: { region: string | undefined; className?: string }) { - const regionIcon = REGION_ICON[region] ?? REGION_ICON.unknown; - - if (typeof regionIcon === "string") { - return ( - - ); - } - - return ; -} - -export function LobbyRegion({ - projectId, - regionId, - showLabel, -}: LobbyRegionProps) { - const { data: region } = useSuspenseQuery( - projectRegionQueryOptions({ projectId, regionId }), - ); - - const regionKey = getRegionKey(region?.regionNameId); - - if (showLabel) { - return ( - - - - {showLabel === "abbreviated" - ? regionKey - : (REGION_LABEL[regionKey] ?? REGION_LABEL.unknown)} - - - ); - } - - return ( - - - - } - /> - ); -} - -export function LobbyRegionIcon({ - regionNameId, - className, -}: { regionNameId: string; className?: string }) { - return ; -} - -export function LobbyRegionName({ regionNameId }: { regionNameId: string }) { - const regionKey = getRegionKey(regionNameId); - return REGION_LABEL[regionKey] ?? REGION_LABEL.unknown; -} diff --git a/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-sort-select.tsx b/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-sort-select.tsx deleted file mode 100644 index bb69da0f57..0000000000 --- a/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-sort-select.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { - Label, - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@rivet-gg/components"; -import type { ComponentProps } from "react"; - -const sortOptions = [ - { label: "by creation date (newest first)", value: "creation-date-newest" }, - { label: "by creation date (oldest first)", value: "creation-date-oldest" }, - { label: "by status", value: "status" }, - { label: "by player count (biggest first)", value: "player-count-biggest" }, - { - label: "by player count (smallest first)", - value: "player-count-smallest", - }, -] as const; - -export const SORT_VALUES = sortOptions.map((option) => option.value); - -interface LobbySortSelectProps extends ComponentProps {} - -export function LobbySortSelect(props: LobbySortSelectProps) { - return ( -
- - -
- ); -} diff --git a/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-stats.tsx b/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-stats.tsx deleted file mode 100644 index 2e4ff49436..0000000000 --- a/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-stats.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import type { Rivet } from "@rivet-gg/api-full"; -import { Flex, Progress, ScrollArea, Strong } from "@rivet-gg/components"; -import { filesize } from "filesize"; -import { LobbyCPUStats } from "./lobby-cpu-stats"; -import { LobbyMemoryStats } from "./lobby-memory-stats"; - -interface LobbyStatsProps extends Rivet.cloud.SvcMetrics { - lobbyId: string; - metricsAt: number; -} - -export function LobbyStats({ - cpu, - memory, - metricsAt, - allocatedMemory, - lobbyId, -}: LobbyStatsProps) { - const syncId = `stats-${lobbyId}`; - - const memoryPercentage = - (memory[memory.length - 1] / (allocatedMemory || 1)) * 100; - - const cpuPercentage = cpu[cpu.length - 1]; - - return ( - -
-
-

Memory Usage

- - - - - - {memoryPercentage.toFixed(2)}% - - - -

- - {filesize(memory[memory.length - 1])} - {" "} - /{" "} - - {filesize(allocatedMemory || 1)} - {" "} - Total -

-
-
-

CPU Usage

- - - - - - - {cpuPercentage.toFixed(2)}% - - - -
-
-
- ); -} diff --git a/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-status.tsx b/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-status.tsx deleted file mode 100644 index ede7954ec4..0000000000 --- a/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-status.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { Badge } from "@rivet-gg/components"; -import { - Icon, - faSealExclamation, - faSealQuestion, - faSpinnerThird, -} from "@rivet-gg/icons"; -import type { LobbyStatus } from "../../data/lobby-status"; - -interface LobbyStatusBadgeProps { - status: LobbyStatus; -} - -export function LobbyStatusBadge({ status }: LobbyStatusBadgeProps) { - if (status === "running") { - return ( - -
- Running - - ); - } - if (status === "failed") { - return ( - - - Failed - - ); - } - - if (status === "not-started") { - return ( - - - Not Started - - ); - } - - if (status === "closed") { - return Finished; - } - - if (status === "idle") { - return Idle; - } - - return ( - - - Unknown - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-summary.tsx b/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-summary.tsx deleted file mode 100644 index 9c19a83227..0000000000 --- a/frontend/apps/hub/src/domains/project/components/matchmaker/lobby-summary.tsx +++ /dev/null @@ -1,120 +0,0 @@ -import { - Button, - CopyArea, - CopyButton, - Flex, - Skeleton, - WithTooltip, -} from "@rivet-gg/components"; -import type { PropsWithChildren, ReactNode } from "react"; -import { - type LobbySummary as LobbySummaryType, - useEnvironmentMatchmakeDeleteLobbyMutation, -} from "../../queries"; -import { LobbyRegion } from "./lobby-region"; - -function Container({ children }: PropsWithChildren) { - return ( - - {children} - - ); -} - -interface LobbySummaryProps extends LobbySummaryType { - isLive?: boolean; - projectId: string; - rightSide?: ReactNode; -} - -export function LobbySummary({ - lobbyGroupNameId, - lobbyId, - projectId, - regionId, - rightSide, - namespaceId: environmentId, - isLive, -}: LobbySummaryProps) { - const { mutate: deleteLobby } = - useEnvironmentMatchmakeDeleteLobbyMutation(); - - return ( - - - - - - - } - content="Lobby Group Name" - /> - - - - - - - - {isLive ? ( - - ) : null} - - - - - {rightSide} - - - - ); -} - -LobbySummary.Skeleton = function LobbyLogsSummarySkeleton() { - return ( - -
- - - - -
- - -
- ); -}; diff --git a/frontend/apps/hub/src/domains/project/components/matchmaker/matchmaker-list-lobby-button.tsx b/frontend/apps/hub/src/domains/project/components/matchmaker/matchmaker-list-lobby-button.tsx deleted file mode 100644 index d2bc60abfc..0000000000 --- a/frontend/apps/hub/src/domains/project/components/matchmaker/matchmaker-list-lobby-button.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import { - Badge, - Button, - Flex, - SmallText, - Uptime, - WithTooltip, -} from "@rivet-gg/components"; -import { Icon, faUsers } from "@rivet-gg/icons"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { Link } from "@tanstack/react-router"; -import { - type LiveLobbyLogs, - type LobbySummary, - projectEnvironmentLobbyQueryOptions, -} from "../../queries"; -import { LobbyRegion } from "./lobby-region"; -import { LobbyStatusBadge } from "./lobby-status"; - -type ProjectMatchmakerListLobbyButtonProps = (LobbySummary | LiveLobbyLogs) & { - projectId: string; - isActive?: boolean; -}; -export function ProjectMatchmakerListLobbyButton({ - isActive, - lobbyId, - regionId, - projectId, - lobbyGroupNameId, - readableStatus, - createTs, - ...props -}: ProjectMatchmakerListLobbyButtonProps) { - return ( - - ); -} - -interface ProjectMatchmakerListLobbyPrefilledButtonProps { - projectId: string; - environmentId: string; - lobbyId: string; - isActive?: boolean; -} - -export function ProjectMatchmakerListLobbyPrefilledButton({ - projectId, - environmentId, - lobbyId, - isActive, -}: ProjectMatchmakerListLobbyPrefilledButtonProps) { - const { - data: { lobby }, - } = useSuspenseQuery( - projectEnvironmentLobbyQueryOptions({ - projectId, - environmentId, - lobbyId, - }), - ); - - return ( - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/matchmaker/matchmaker-list-lobby-panel.tsx b/frontend/apps/hub/src/domains/project/components/matchmaker/matchmaker-list-lobby-panel.tsx deleted file mode 100644 index 6445c16f00..0000000000 --- a/frontend/apps/hub/src/domains/project/components/matchmaker/matchmaker-list-lobby-panel.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { Flex, ScrollArea } from "@rivet-gg/components"; -import type { ReactNode } from "react"; -import type { LiveLobbyLogs, LobbySummary } from "../../queries"; -import { ProjectMatchmakerListLobbyButton } from "./matchmaker-list-lobby-button"; - -interface ProjectMatchmakerLobbyListPanelProps { - projectId: string; - lobbies: (LobbySummary | LiveLobbyLogs)[]; - lobbyId?: string; - children?: ReactNode; -} - -export function ProjectMatchmakerLobbyListPanel({ - lobbies, - projectId, - lobbyId, - children, -}: ProjectMatchmakerLobbyListPanelProps) { - return ( - - - <> - {children} - {lobbies.map((lobby) => ( - - ))} - - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/components/matchmaker/matchmaker-list-lobby-preview.tsx b/frontend/apps/hub/src/domains/project/components/matchmaker/matchmaker-list-lobby-preview.tsx deleted file mode 100644 index f3d64da615..0000000000 --- a/frontend/apps/hub/src/domains/project/components/matchmaker/matchmaker-list-lobby-preview.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { - ResizableHandle, - ResizablePanel, - ResizablePanelGroup, - useBreakpoint, -} from "@rivet-gg/components"; -import { type ReactNode, Suspense } from "react"; -import type { LiveLobbyLogs, LobbySummary } from "../../queries"; -import { ProjectMatchmakerListLobbyPrefilledButton } from "./matchmaker-list-lobby-button"; -import { ProjectMatchmakerLobbyListPanel } from "./matchmaker-list-lobby-panel"; -import { ProjectMatchmakerLobbyDetailsPanel } from "./matchmaker-lobby-details-panel"; - -interface ProjectMatchmakerListLobbyPreviewProps { - lobbies: (LobbySummary | LiveLobbyLogs)[]; - lobbyId?: string; - projectId: string; - environmentId: string; - isLive?: boolean; - sort?: ReactNode; -} - -export function ProjectMatchmakerListLobbyPreview({ - lobbies, - lobbyId, - projectId, - environmentId, - isLive, -}: ProjectMatchmakerListLobbyPreviewProps) { - const isMd = useBreakpoint("md"); - const doesLobbyExist = - lobbies.find((lobby) => lobby.lobbyId === lobbyId) !== undefined; - - return ( - - -
- - {!doesLobbyExist && lobbyId ? ( - - ) : null} - -
-
- - -
- - } - > - - -
-
-
- ); -} diff --git a/frontend/apps/hub/src/domains/project/components/matchmaker/matchmaker-lobby-details-panel.tsx b/frontend/apps/hub/src/domains/project/components/matchmaker/matchmaker-lobby-details-panel.tsx deleted file mode 100644 index 398357dd68..0000000000 --- a/frontend/apps/hub/src/domains/project/components/matchmaker/matchmaker-lobby-details-panel.tsx +++ /dev/null @@ -1,137 +0,0 @@ -import { - Flex, - Tabs, - TabsContent, - TabsList, - TabsTrigger, - Text, -} from "@rivet-gg/components"; -import { ErrorBoundary } from "@sentry/react"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { Suspense } from "react"; -import { projectEnvironmentLobbyQueryOptions } from "../../queries"; -import { LobbyLifecycle } from "./lobby-lifecycle"; -import { LobbyLogs } from "./lobby-logs"; -import { LobbyMetrics } from "./lobby-metrics"; -import { LobbyStats } from "./lobby-stats"; -import { LobbySummary } from "./lobby-summary"; - -interface ProjectMatchmakerLobbyDetailsPanelProps { - lobbyId?: string; - projectId: string; - environmentId: string; - isLive?: boolean; -} - -export function ProjectMatchmakerLobbyDetailsPanel({ - lobbyId, - projectId, - environmentId, - isLive, -}: ProjectMatchmakerLobbyDetailsPanelProps) { - if (!lobbyId) { - return ( - - - Please select a lobby from the list on the left. - - - ); - } - - const { - data: { lobby, metrics }, - dataUpdatedAt, - } = useSuspenseQuery( - projectEnvironmentLobbyQueryOptions( - { projectId, environmentId, lobbyId }, - { refetchInterval: isLive ? 1000 : undefined, throwOnError: true }, - ), - ); - - return ( - - - An error occurred while fetching lobby data. - - - } - > - }> - - - - {isLive && metrics ? ( - - ) : null} - - } - /> - - - - - Output - Error - {isLive && metrics ? ( - Monitor - ) : null} - - - }> - - - - - }> - - - - {isLive && metrics ? ( - - }> - - - - ) : null} - - - ); -} - -ProjectMatchmakerLobbyDetailsPanel.Skeleton = () => { - return ( - - - - - ); -}; diff --git a/frontend/apps/hub/src/domains/project/components/tags-select.tsx b/frontend/apps/hub/src/domains/project/components/tags-select.tsx deleted file mode 100644 index 29ba2e7c63..0000000000 --- a/frontend/apps/hub/src/domains/project/components/tags-select.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import { Combobox } from "@rivet-gg/components"; -import { ActorTag } from "@rivet-gg/components/actors"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { actorBuildTagsQueryOptions } from "../queries"; - -interface TagsSelectProps { - projectId: string; - environmentId: string; - value: Record; - onValueChange: (value: Record) => void; - showSelectedOptions?: number; -} - -export function TagsSelect({ - projectId, - environmentId, - value, - onValueChange, - showSelectedOptions, -}: TagsSelectProps) { - const { data } = useSuspenseQuery( - actorBuildTagsQueryOptions({ projectId, environmentId }), - ); - - const valArray = Object.entries(value); - - // upsert custom tags to the list of tags - const tags = [...data]; - for (const [key, value] of valArray) { - const found = data.find( - (tag) => tag.key === key && tag.value === value, - ); - - if (!found) { - tags.push({ key, value }); - } - } - - const options = tags.map((tag) => { - return { - label: ( - - - {tag.key}={tag.value} - - - ), - value: [tag.key, tag.value].join("="), - tag, - }; - }); - - const val = valArray.map(([key, value]) => { - return [key, value].join("="); - }); - - const handleValueChange = (value: string[]) => { - onValueChange( - Object.fromEntries( - value.map((v) => { - // its safe to split by "=" because the value is a tag - const [key, value] = v.split("="); - return [key.trim(), value.trim()]; - }), - ), - ); - }; - - const handleCreateOption = (option: string) => { - const parts = option.split("="); - if (parts.length !== 2) return; - - const [key, value] = parts.map((part) => part.trim()); - if (!key || !value) return; - - onValueChange(Object.fromEntries([...valArray, [key, value]])); - }; - - return ( - { - const tagKey = option.tag.key.toLowerCase(); - const tagValue = option.tag.value.toLowerCase(); - - if (search.includes("=")) { - const [key, value] = search.split("="); - return tagKey.includes(key) && tagValue.includes(value); - } - return tagKey.includes(search) || tagValue.includes(search); - }} - className="w-full min-w-[20rem]" - /> - ); -} diff --git a/frontend/apps/hub/src/domains/project/data/billing-calculate-usage.ts b/frontend/apps/hub/src/domains/project/data/billing-calculate-usage.ts deleted file mode 100644 index da9df81ac7..0000000000 --- a/frontend/apps/hub/src/domains/project/data/billing-calculate-usage.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { Rivet as RivetEe } from "@rivet-gg/api-ee"; -import { millisecondsToMonths } from "@rivet-gg/components"; - -export const PRICE_MAP = { - [RivetEe.ee.billing.Plan.Trial]: 0, - [RivetEe.ee.billing.Plan.Indie]: 20.0, - [RivetEe.ee.billing.Plan.Studio]: 200.0, -}; -const CREIDTS_MAP = { - [RivetEe.ee.billing.Plan.Trial]: 5.0, - [RivetEe.ee.billing.Plan.Indie]: 48.21, - [RivetEe.ee.billing.Plan.Studio]: 29.0, -}; -export const BILLING_PLANS_CREDITS_VISIBILITY: RivetEe.ee.billing.Plan[] = [ - RivetEe.ee.billing.Plan.Indie, - RivetEe.ee.billing.Plan.Trial, -]; - -const FACTOR = 16.07; - -export function calculateUsedCredits({ - usage, - plan, -}: { - usage: RivetEe.ee.billing.GameUsage | undefined; - plan: RivetEe.ee.billing.Plan; -}) { - const totalUptime = - usage?.regions.reduce((acc, region) => acc + region.uptime, 0) ?? 0; - const monthsOfUptime = millisecondsToMonths(totalUptime); - const usedCredits = monthsOfUptime * FACTOR; - - const overage = Math.max(0, usedCredits - CREIDTS_MAP[plan]); - - return { - max: CREIDTS_MAP[plan], - used: usedCredits, - remaining: CREIDTS_MAP[plan] - usedCredits, - overage, - total: PRICE_MAP[plan] + overage, - }; -} diff --git a/frontend/apps/hub/src/domains/project/data/environment-context.tsx b/frontend/apps/hub/src/domains/project/data/environment-context.tsx deleted file mode 100644 index ebca61ab76..0000000000 --- a/frontend/apps/hub/src/domains/project/data/environment-context.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import type { Rivet } from "@rivet-gg/api-full"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { type ReactNode, createContext, useContext } from "react"; -import { environmentByIdQueryOptions } from "../queries"; -import { useProject } from "./project-context"; - -export const EnvironmentContext = createContext< - Rivet.cloud.NamespaceSummary | undefined ->(undefined); - -export function EnvironmentContextProvider({ - children, - environmentNameId, -}: { - children: ReactNode; - environmentNameId: string; -}) { - const project = useProject(); - const { data: environment } = useSuspenseQuery( - environmentByIdQueryOptions({ - projectId: project.gameId, - environmentNameId, - }), - ); - - return ( - - {children} - - ); -} - -function useEnvironmentContext() { - const context = useContext(EnvironmentContext); - if (!context) { - throw new Error( - "useEnvironmentContext must be used within a EnvironmentContextProvider", - ); - } - return context; -} - -export function useEnvironment() { - return useEnvironmentContext(); -} diff --git a/frontend/apps/hub/src/domains/project/data/lobby-status.ts b/frontend/apps/hub/src/domains/project/data/lobby-status.ts deleted file mode 100644 index fd52c54b97..0000000000 --- a/frontend/apps/hub/src/domains/project/data/lobby-status.ts +++ /dev/null @@ -1,57 +0,0 @@ -import type { Rivet } from "@rivet-gg/api-full"; - -export type LobbyStatus = - | "running" - | "not-started" - | "failed" - | "closed" - | "idle" - | "outdated" - | "unknown"; - -export function formatLobbyStatus(status: LobbyStatus) { - const map: Record = { - running: "Running", - "not-started": "Not started", - failed: "Failed", - closed: "Closed", - unknown: "Unknown status", - idle: "Idle", - outdated: "Outdated", - }; - - return map[status]; -} - -export function getLiveLobbyStatus( - lobby: Rivet.cloud.LobbySummaryAnalytics, -): LobbyStatus { - if (lobby.isClosed) { - return "closed"; - } - if (lobby.isIdle) { - return "idle"; - } - if (lobby.isOutdated) { - return "outdated"; - } - if (lobby.isReady) { - return "running"; - } - return "unknown"; -} - -export function getLobbyStatus( - status: Rivet.cloud.LogsLobbyStatus, - startTs: Date | undefined, -): LobbyStatus { - if (status.stopped?.stopTs) { - return status.stopped.failed ? "failed" : "closed"; - } - - if (status.running !== undefined) { - return startTs ? "running" : "not-started"; - } - - return "unknown"; -} diff --git a/frontend/apps/hub/src/domains/project/data/project-context.tsx b/frontend/apps/hub/src/domains/project/data/project-context.tsx deleted file mode 100644 index 243f21ef34..0000000000 --- a/frontend/apps/hub/src/domains/project/data/project-context.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { useAuth } from "@/domains/auth/contexts/auth"; -import { ls } from "@/lib/ls"; -import type { Rivet } from "@rivet-gg/api-full"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { type ReactNode, createContext, useContext, useEffect } from "react"; -import { projectByIdQueryOptions } from "../queries"; - -export const ProjectContext = createContext( - undefined, -); - -export function ProjectContextProvider({ - children, - projectNameId, -}: { - children: ReactNode; - projectNameId: string; -}) { - const auth = useAuth(); - const { data: project } = useSuspenseQuery( - projectByIdQueryOptions(projectNameId), - ); - - useEffect(() => { - ls.recentTeam.set(auth, project.developer.groupId); - }, [auth, project.developer.groupId]); - - return ( - - {children} - - ); -} - -function useProjectContext() { - const context = useContext(ProjectContext); - if (!context) { - throw new Error( - "useProjectContext must be used within a ProjectContextProvider", - ); - } - return context; -} - -export function useProject() { - return useProjectContext(); -} diff --git a/frontend/apps/hub/src/domains/project/forms/actor-create-form.tsx b/frontend/apps/hub/src/domains/project/forms/actor-create-form.tsx deleted file mode 100644 index f169575b05..0000000000 --- a/frontend/apps/hub/src/domains/project/forms/actor-create-form.tsx +++ /dev/null @@ -1,170 +0,0 @@ -// import { -// FormControl, -// FormField, -// FormItem, -// FormLabel, -// FormMessage, -// Label, -// createSchemaForm, -// } from "@rivet-gg/components"; -// import { JsonCode } from "@rivet-gg/components/code-mirror"; -// import { type UseFormReturn, useFormContext } from "react-hook-form"; -// import z from "zod"; -// import { BuildSelect } from "../components/build-select"; -// import { RegionSelect } from "../components/region-select"; - -// import { -// Tags as TagsInput, -// formSchema as tagsFormSchema, -// } from "@/domains/project/forms/build-tags-form"; -// import { useSuspenseQuery } from "@tanstack/react-query"; -// import { useState } from "react"; -// import { actorBuildsQueryOptions } from "../queries"; - -// const jsonValid = z.custom((value) => { -// try { -// JSON.parse(value); -// return true; -// } catch { -// return false; -// } -// }); - -// export const formSchema = z.object({ -// buildId: z.string().nonempty("Build is required"), -// regionId: z.string(), -// parameters: jsonValid.optional(), -// tags: tagsFormSchema.shape.tags, -// }); - -// export type FormValues = z.infer; -// export type SubmitHandler = ( -// values: FormValues, -// form: UseFormReturn, -// ) => Promise; - -// const { Form, Submit } = createSchemaForm(formSchema); -// export { Form, Submit }; - -// export const Build = ({ -// projectNameId, -// environmentNameId, -// }: { projectNameId: string; environmentNameId: string }) => { -// const { control } = useFormContext(); -// return ( -// ( -// -// Build -// -// -// -// -// -// )} -// /> -// ); -// }; - -// export const Region = ({ -// projectNameId, -// environmentNameId, -// }: { projectNameId: string; environmentNameId: string }) => { -// const { control } = useFormContext(); -// return ( -// ( -// -// Region -// -// -// -// -// -// )} -// /> -// ); -// }; - -// export const Parameters = () => { -// const { control } = useFormContext(); -// return ( -// ( -// -// Parameters -// -// -// -// -// -// )} -// /> -// ); -// }; - -// export const Tags = ({ -// projectNameId, -// environmentNameId, -// }: { projectNameId: string; environmentNameId: string }) => { -// const { data: builds } = useSuspenseQuery( -// actorBuildsQueryOptions({ projectNameId, environmentNameId }), -// ); - -// const [tagKeys, setTagKeys] = useState(() => -// Array.from( -// new Set( -// builds?.flatMap((build) => Object.keys(build.tags)), -// ).values(), -// ).map((key) => ({ -// label: key, -// value: key, -// })), -// ); - -// const [tagValues, setTagValues] = useState(() => -// Array.from( -// new Set( -// builds?.flatMap((build) => Object.values(build.tags)), -// ).values(), -// ).map((key) => ({ label: key, value: key })), -// ); - -// return ( -//
-// -// -// setTagKeys((opts) => [ -// ...opts, -// { label: option, value: option }, -// ]) -// } -// onCreateValueOption={(option) => -// setTagValues((opts) => [ -// ...opts, -// { label: option, value: option }, -// ]) -// } -// /> -//
-// ); -// }; diff --git a/frontend/apps/hub/src/domains/project/forms/backend-env-autoscaling-config-form.tsx b/frontend/apps/hub/src/domains/project/forms/backend-env-autoscaling-config-form.tsx deleted file mode 100644 index 1d06df1fe1..0000000000 --- a/frontend/apps/hub/src/domains/project/forms/backend-env-autoscaling-config-form.tsx +++ /dev/null @@ -1,136 +0,0 @@ -import { - Flex, - FormControl, - FormDescription, - FormField, - FormItem, - FormLabel, - FormMessage, - Grid, - Link, - Slider, - SmallText, - createSchemaForm, -} from "@rivet-gg/components"; -import { type UseFormReturn, useFormContext } from "react-hook-form"; -import z from "zod"; - -export const AUTOSCALING_VALUE_MAP = [ - { value: 0.25, memory: 1, vcpu: 0.25 }, - { value: 0.5, memory: 2, vcpu: 0.5 }, - { value: 1, memory: 4, vcpu: 1 }, - { value: 2, memory: 8, vcpu: 2 }, - { value: 3, memory: 12, vcpu: 3 }, - { value: 4, memory: 16, vcpu: 4 }, - { value: 5, memory: 20, vcpu: 5 }, - { value: 6, memory: 24, vcpu: 6 }, - { value: 7, memory: 28, vcpu: 7 }, - { value: 8, memory: 32, vcpu: 8 }, -]; - -export const AUTOSCALING_VALUE_TO_INDEX_MAP = Object.fromEntries( - AUTOSCALING_VALUE_MAP.map(({ value }, index) => [value, index]), -); - -export const formSchema = z.object({ - autoscalling: z.object({ - min: z.coerce - .number() - .min(0) - .max(AUTOSCALING_VALUE_MAP.length - 1), - max: z.coerce - .number() - .min(0) - .max(AUTOSCALING_VALUE_MAP.length - 1), - }), -}); - -export type FormValues = z.infer; -export type SubmitHandler = ( - values: FormValues, - form: UseFormReturn, -) => Promise; - -const { Form, Submit } = createSchemaForm(formSchema); -export { Form, Submit }; - -const AutoscalingLabel = () => { - const { watch } = useFormContext(); - const autoscaling = watch("autoscalling"); - - const min = AUTOSCALING_VALUE_MAP[autoscaling.min]; - const max = AUTOSCALING_VALUE_MAP[autoscaling.max]; - return ( - - - Min: {min.vcpu} vCPU, {min.memory} GB of RAM - - - Max: {max.vcpu} vCPU, {max.memory} GB of RAM - - - ); -}; - -export const Autoscaling = () => { - const { control } = useFormContext(); - return ( - ( - - Autoscaling - - - - - - field.onChange({ - min: value[0], - max: value[1], - }) - } - step={1} - min={0} - max={AUTOSCALING_VALUE_MAP.length - 1} - value={[field.value.min, field.value.max]} - defaultValue={[ - field.value.min, - field.value.max, - ]} - /> - - {AUTOSCALING_VALUE_MAP.map( - ({ value }, index) => ( - - {value} - - ), - )} - - - - - - - Need more resources?{" "} - - Contact support. - - - - - )} - /> - ); -}; diff --git a/frontend/apps/hub/src/domains/project/forms/backend-env-variables-form.tsx b/frontend/apps/hub/src/domains/project/forms/backend-env-variables-form.tsx deleted file mode 100644 index 248228b942..0000000000 --- a/frontend/apps/hub/src/domains/project/forms/backend-env-variables-form.tsx +++ /dev/null @@ -1,173 +0,0 @@ -import { - Button, - Flex, - FormControl, - FormDescription, - FormFieldContext, - FormItem, - FormLabel, - FormMessage, - Input, - Strong, - Switch, - Text, - createSchemaForm, -} from "@rivet-gg/components"; -import { Icon, faTrash } from "@rivet-gg/icons"; -import { - type Control, - type UseFormReturn, - useController, - useFieldArray, - useFormContext, - useWatch, -} from "react-hook-form"; -import z from "zod"; - -export const formSchema = z.object({ - variables: z - .array( - z.object({ - key: z.string().min(1), - value: z.string(), - isSecret: z.boolean().default(false), - }), - ) - .superRefine((variables, ctx) => { - const variablesSet = new Set(); - for (const [idx, variable] of [...variables].reverse().entries()) { - if (variablesSet.has(variable.key)) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - path: [idx, "key"], - message: "Variable keys must be unique", - }); - } - variablesSet.add(variable.key); - } - }), -}); - -export type FormValues = z.infer; -export type SubmitHandler = ( - values: FormValues, - form: UseFormReturn, -) => Promise; - -const { Form, Submit } = createSchemaForm(formSchema); -export { Form, Submit }; - -export const Variables = () => { - const { control, register } = useFormContext(); - const { fields, append, remove } = useFieldArray({ - name: "variables", - control, - }); - - return ( - <> - {fields.length === 0 ? ( - There's no variables added. - ) : null} - - {fields.map((field, index) => ( - - - - Key - - - - - - - - - - Value - - - - - - - - - - remove(index)} /> - - - ))} - - ); -}; - -const EncryptInformation = ({ - control, - index, -}: { control: Control; index: number }) => { - const isSecret = useWatch({ - control, - name: `variables.${index}.isSecret`, - }); - return ( - - {isSecret ? ( - <> - This value will no longer be viewable once - saved. - - ) : null} - - ); -}; - -function Encrypt({ index, onRemove }: { index: number; onRemove: () => void }) { - const { - field: { onChange, value }, - } = useController({ - name: `variables.${index}.isSecret` as const, - }); - - return ( - - Encrypt - - - - - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/forms/cdn-manage-auth-users-form.tsx b/frontend/apps/hub/src/domains/project/forms/cdn-manage-auth-users-form.tsx deleted file mode 100644 index b51b661ab8..0000000000 --- a/frontend/apps/hub/src/domains/project/forms/cdn-manage-auth-users-form.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import { - Button, - Flex, - FormControl, - FormFieldContext, - FormItem, - FormLabel, - FormMessage, - Input, - Text, - createSchemaForm, -} from "@rivet-gg/components"; -import { Icon, faTrash } from "@rivet-gg/icons"; -import { - type UseFormReturn, - useFieldArray, - useFormContext, -} from "react-hook-form"; -import z from "zod"; - -export const formSchema = z.object({ - users: z - .array( - z.object({ - user: z.string().min(1), - password: z.string(), - }), - ) - .superRefine((users, ctx) => { - const userSet = new Set(); - for (const [idx, user] of [...users].reverse().entries()) { - if (userSet.has(user.user)) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - path: [idx, "user"], - message: "Usernames must be unique", - }); - } - userSet.add(user.user); - } - }), -}); - -export type FormValues = z.infer; -export type SubmitHandler = ( - values: FormValues, - form: UseFormReturn, -) => Promise; - -const { Form, Submit } = createSchemaForm(formSchema); -export { Form, Submit }; - -export const Users = () => { - const { control, register } = useFormContext(); - const { fields, append, remove } = useFieldArray({ - name: "users", - control, - }); - - return ( - <> - {fields.length === 0 ? There's no users added. : null} - {fields.map((field, index) => ( - - - - Username - - - - - - - - - - Password - - - - - - - - - - - ))} - - - ); -}; diff --git a/frontend/apps/hub/src/domains/project/forms/cdn-new-custom-domain-form.tsx b/frontend/apps/hub/src/domains/project/forms/cdn-new-custom-domain-form.tsx deleted file mode 100644 index e76bce70cf..0000000000 --- a/frontend/apps/hub/src/domains/project/forms/cdn-new-custom-domain-form.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, - Input, - createSchemaForm, -} from "@rivet-gg/components"; -import { type UseFormReturn, useFormContext } from "react-hook-form"; -import z from "zod"; - -const DOMAIN_REGEX = - /^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$/; - -export const formSchema = z.object({ - name: z.string().regex(DOMAIN_REGEX, "Invalid domain"), -}); - -export type FormValues = z.infer; -export type SubmitHandler = ( - values: FormValues, - form: UseFormReturn, -) => Promise; - -const { Form, Submit } = createSchemaForm(formSchema); -export { Form, Submit }; - -export const Name = () => { - const { control } = useFormContext(); - return ( - ( - - Domain name - - - - - - )} - /> - ); -}; diff --git a/frontend/apps/hub/src/domains/project/forms/create-project-form.tsx b/frontend/apps/hub/src/domains/project/forms/create-project-form.tsx deleted file mode 100644 index 0896ec98f9..0000000000 --- a/frontend/apps/hub/src/domains/project/forms/create-project-form.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { GroupSelect } from "@/domains/group/components/group-select"; -import { useDialog } from "@/hooks/use-dialog"; -import { - FormField, - FormItem, - FormLabel, - FormMessage, - createSchemaForm, -} from "@rivet-gg/components"; -import { type UseFormReturn, useFormContext } from "react-hook-form"; -import z from "zod"; -import * as GroupCreateProjectForm from "./group-create-project-form"; - -export const formSchema = z.intersection( - z.object({ developerGroupId: z.string().min(1, "Required") }), - GroupCreateProjectForm.formSchema, -); - -export type FormValues = z.infer; -export type SubmitHandler = ( - values: FormValues, - form: UseFormReturn, -) => Promise; - -const { Form, Submit } = createSchemaForm(formSchema); -export { Form, Submit }; - -export const Name = GroupCreateProjectForm.Name; -export const Slug = GroupCreateProjectForm.Slug; - -export const Group = () => { - const { setValue, control } = useFormContext(); - const { dialog, open, close } = useDialog.CreateGroup({ - onSuccess: (data) => { - setValue("developerGroupId", data.groupId, { - shouldDirty: true, - shouldTouch: true, - }); - close(); - }, - }); - return ( - <> - {dialog} - ( - - Team - - - - )} - /> - - ); -}; diff --git a/frontend/apps/hub/src/domains/project/forms/environment-create-form.tsx b/frontend/apps/hub/src/domains/project/forms/environment-create-form.tsx deleted file mode 100644 index 7150f5d91f..0000000000 --- a/frontend/apps/hub/src/domains/project/forms/environment-create-form.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import { - safeAsyncValidation, - validateAgainstApi, -} from "@/lib/async-validation"; -import { convertStringToId } from "@/lib/utils"; -import { rivetClient } from "@/queries/global"; -import { - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, - Input, - createSchemaForm, -} from "@rivet-gg/components"; -import { type UseFormReturn, useFormContext } from "react-hook-form"; -import z from "zod"; - -export const formSchema = z - .object({ - name: z.string().max(25), - slug: z.string().max(25).optional(), - projectId: z.string(), - }) - .superRefine(async (arg, ctx) => { - await safeAsyncValidation(ctx, async () => { - const res = - await rivetClient.cloud.games.namespaces.validateGameNamespace( - arg.projectId, - { - displayName: arg.name, - nameId: arg.slug || convertStringToId(arg.name), - }, - ); - - validateAgainstApi({ - group: "GAME_NAMESPACE", - errors: res.errors, - }).setSchemaIssues(ctx, { - name: "display-name", - slug: "name-id", - }); - }); - - return z.NEVER; - }); - -export type FormValues = z.infer; -export type SubmitHandler = ( - values: FormValues, - form: UseFormReturn, -) => Promise; - -const { Form, Submit } = createSchemaForm(formSchema); -export { Form, Submit }; - -export const Name = () => { - const { control } = useFormContext(); - return ( - ( - - Name - - - - - - )} - /> - ); -}; - -export const Slug = () => { - const { control, watch } = useFormContext(); - - const name = watch("name"); - - return ( - ( - - Slug - - { - const value = event.target.value - .replace(/[\s-]+/g, "-") - .toLowerCase(); - field.onChange({ target: { value } }); - }} - /> - - - - )} - /> - ); -}; diff --git a/frontend/apps/hub/src/domains/project/forms/group-create-project-form.tsx b/frontend/apps/hub/src/domains/project/forms/group-create-project-form.tsx deleted file mode 100644 index d5244000b2..0000000000 --- a/frontend/apps/hub/src/domains/project/forms/group-create-project-form.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import { - safeAsyncValidation, - validateAgainstApi, -} from "@/lib/async-validation"; -import { convertStringToId } from "@/lib/utils"; -import { rivetClient } from "@/queries/global"; -import { - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, - Input, - createSchemaForm, -} from "@rivet-gg/components"; -import { type UseFormReturn, useFormContext } from "react-hook-form"; -import z from "zod"; - -export const formSchema = z - .object({ - name: z - .string() - .max(25) - .refine((value) => value.trim() !== "" && value.trim() === value, { - message: "Name cannot be empty or contain whitespaces", - }), - slug: z.string().max(25).optional(), - }) - .superRefine(async (arg, ctx) => { - await safeAsyncValidation(ctx, async () => { - const res = await rivetClient.cloud.games.validateGame({ - displayName: arg.name, - nameId: arg.slug || convertStringToId(arg.name), - }); - - validateAgainstApi({ - group: "GAME", - errors: res.errors, - }).setSchemaIssues(ctx, { - name: "display-name", - slug: "name-id", - }); - }); - - return z.NEVER; - }); - -export type FormValues = z.infer; -export type SubmitHandler = ( - values: FormValues, - form: UseFormReturn, -) => Promise; - -const { Form, Submit, SetValue } = createSchemaForm(formSchema); -export { Form, Submit, SetValue }; - -export const Name = ({ className }: { className?: string }) => { - const { control } = useFormContext(); - return ( - ( - - Project Name - - - - - - )} - /> - ); -}; - -export const Slug = ({ className }: { className?: string }) => { - const { control, watch } = useFormContext(); - - const name = watch("name"); - - return ( - ( - - Slug - - { - const value = convertStringToId( - event.target.value, - ); - field.onChange({ target: { value } }); - }} - /> - - - - )} - /> - ); -}; diff --git a/frontend/apps/hub/src/domains/project/forms/matchmaker-lobby-config-form.tsx b/frontend/apps/hub/src/domains/project/forms/matchmaker-lobby-config-form.tsx deleted file mode 100644 index 66b3d7586a..0000000000 --- a/frontend/apps/hub/src/domains/project/forms/matchmaker-lobby-config-form.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import { - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, - Input, - createSchemaForm, -} from "@rivet-gg/components"; -import { type UseFormReturn, useFormContext } from "react-hook-form"; -import z from "zod"; - -const LOBBY_COUNT_MAX = 32768 - 1; - -export const formSchema = z.object({ - lobbyCountMax: z.coerce.number().min(1).max(LOBBY_COUNT_MAX), - maxPlayers: z.coerce.number().min(1).max(LOBBY_COUNT_MAX), -}); - -export type FormValues = z.infer; -export type SubmitHandler = ( - values: FormValues, - form: UseFormReturn, -) => Promise; - -const { Form, Submit } = createSchemaForm(formSchema); -export { Form, Submit }; - -export const LobbyCountMax = () => { - const { control } = useFormContext(); - return ( - ( - - Max lobby count - - - - - - )} - /> - ); -}; - -export const MaxPlayers = () => { - const { control } = useFormContext(); - return ( - ( - - Max players - - - - - - )} - /> - ); -}; diff --git a/frontend/apps/hub/src/domains/project/forms/project-billing-form.tsx b/frontend/apps/hub/src/domains/project/forms/project-billing-form.tsx deleted file mode 100644 index 0f268bc90a..0000000000 --- a/frontend/apps/hub/src/domains/project/forms/project-billing-form.tsx +++ /dev/null @@ -1,207 +0,0 @@ -import { - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, - Input, - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, - createSchemaForm, - formatCurrency, -} from "@rivet-gg/components"; -import { useEffect } from "react"; -import { type UseFormReturn, useFormContext } from "react-hook-form"; -import z from "zod"; - -export const hardwareTierValues = [ - { value: "1/8", label: "1/8 core", multiplier: 1 / 8 }, - { value: "1/4", label: "1/4 core", multiplier: 1 / 4 }, - { value: "1/2", label: "1/2 core", multiplier: 1 / 2 }, - { value: "1", label: "1 core", multiplier: 1 }, - { value: "2", label: "2 cores", multiplier: 2 }, - { value: "4", label: "4 cores", multiplier: 4 }, -]; - -const PRICE_PER_CORE = 22.76; - -const MAX_CORES = 32768; - -export const formSchema = z.object({ - hardwareTier: z.string(), - capacity: z.array( - z.object({ - regionId: z.string(), - cores: z.coerce.number().min(0).max(MAX_CORES), - }), - ), -}); - -export type FormValues = z.infer; -export type SubmitHandler = ( - values: FormValues, - form: UseFormReturn, -) => Promise; - -const { Form, Submit, Reset } = createSchemaForm(formSchema); -export { Form, Submit, Reset }; - -export const HardwareTier = () => { - const { control } = useFormContext(); - return ( - ( - - Dedicated hardware - - - - )} - /> - ); -}; - -export const HardwareMultiplier = () => { - const { watch, setValue } = useFormContext(); - - useEffect(() => { - let lastHardwareTier: string | undefined; - const { unsubscribe } = watch((value) => { - if (lastHardwareTier === value.hardwareTier) return; - if (!value.hardwareTier || !value.capacity) return; - const lastHardwareTierValue = hardwareTierValues.find( - (item) => item.value === lastHardwareTier, - ); - const currentHardwareTierValue = hardwareTierValues.find( - (item) => item.value === value.hardwareTier, - ); - - lastHardwareTier = value.hardwareTier; - if (!currentHardwareTierValue || !lastHardwareTierValue) return; - - setValue( - "capacity", - value.capacity?.map((item) => ({ - cores: Math.ceil( - ((item?.cores ?? 1) * - lastHardwareTierValue.multiplier) / - currentHardwareTierValue.multiplier, - ), - regionId: item?.regionId ?? "", - })) ?? [], - ); - - lastHardwareTier = value.hardwareTier; - }); - return () => unsubscribe(); - }, [setValue, watch]); - - return null; -}; - -interface CapacityProps { - index: number; - regionId: string; -} - -export const Capacity = ({ index, regionId }: CapacityProps) => { - const { control, register } = useFormContext(); - return ( - <> - ( - - - - - )} - /> - - - ); -}; - -export const HardwareTierValueLabel = () => { - const { watch } = useFormContext(); - - const hardwareTier = watch("hardwareTier"); - - const hardwareTierValue = hardwareTierValues.find( - (item) => item.value === hardwareTier, - ); - return hardwareTierValue?.label ?? "1 core"; -}; - -interface CapacityValueProps { - children: (value: { regionId: string; cores: number }[]) => React.ReactNode; -} - -export const CapacityValue = ({ children }: CapacityValueProps) => { - const { watch } = useFormContext(); - const capacity = watch("capacity"); - - return <>{children(capacity)}; -}; - -interface RegionTotalPriceProps { - index: number; -} - -export const RegionTotalPrice = ({ index }: RegionTotalPriceProps) => { - const { watch } = useFormContext(); - const cores = watch(`capacity.${index}.cores`); - const hardwareTier = watch("hardwareTier"); - - const hardwareTierValue = - hardwareTierValues.find((item) => item.value === hardwareTier) - ?.multiplier ?? 1; - - return <>{formatCurrency(cores * PRICE_PER_CORE * hardwareTierValue)}; -}; - -export const TotalPrice = () => { - const { watch } = useFormContext(); - const capacity = watch("capacity"); - const hardwareTier = watch("hardwareTier"); - - const total = capacity.reduce((acc, item) => { - const hardwareTierValue = - hardwareTierValues.find((tier) => tier.value === hardwareTier) - ?.multiplier ?? 1; - return acc + item.cores * PRICE_PER_CORE * hardwareTierValue; - }, 0); - - return <>{formatCurrency(total)}; -}; diff --git a/frontend/apps/hub/src/domains/project/forms/project-logo-form.tsx b/frontend/apps/hub/src/domains/project/forms/project-logo-form.tsx deleted file mode 100644 index 90c0224f02..0000000000 --- a/frontend/apps/hub/src/domains/project/forms/project-logo-form.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { - FileInput, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, - createSchemaForm, - fileSize, -} from "@rivet-gg/components"; -import { type UseFormReturn, useFormContext } from "react-hook-form"; -import z from "zod"; - -const allowedTypes = ["image/png", "image/jpeg"]; - -export const formSchema = z.object({ - logo: z - .custom() - .refine( - (file) => file.size <= fileSize.megabytes(2), - "File size should be less than 2MB.", - ) - .refine( - (file) => allowedTypes.includes(file.type), - `File type should be one of ${allowedTypes.join(", ")}`, - ), -}); - -export type FormValues = z.infer; -export type SubmitHandler = ( - values: FormValues, - form: UseFormReturn, -) => Promise; - -const { Form, Submit } = createSchemaForm(formSchema); -export { Form, Submit }; - -export const Logo = () => { - const { control } = useFormContext(); - return ( - ( - - Logo - - - name="logo" - field={field} - accept={allowedTypes.join(", ")} - /> - - - - )} - /> - ); -}; diff --git a/frontend/apps/hub/src/domains/project/forms/route-edit-form.tsx b/frontend/apps/hub/src/domains/project/forms/route-edit-form.tsx deleted file mode 100644 index fda88e4b66..0000000000 --- a/frontend/apps/hub/src/domains/project/forms/route-edit-form.tsx +++ /dev/null @@ -1,348 +0,0 @@ -import { bootstrapQueryOptions } from "@/domains/auth/queries/bootstrap"; -import { queryClient } from "@/queries/global"; -import { - Button, - Checkbox, - Code, - Combobox, - type ComboboxOption, - FormControl, - FormDescription, - FormField, - FormFieldContext, - FormItem, - FormLabel, - FormMessage, - Input, - createSchemaForm, -} from "@rivet-gg/components"; -import { Icon, faTrash } from "@rivet-gg/icons"; -import { - type UseFormReturn, - useFieldArray, - useFormContext, -} from "react-hook-form"; -import z from "zod"; - -export const formSchema = z.object({ - stripPrefix: z.boolean().optional(), - routeSubpaths: z.boolean().optional(), - hostname: z - .string() - .min(1) - .refine((value) => { - const regex = /^[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*$/; - return regex.test(value); - }, "Hostname must be a valid domain name") - .refine( - async (value) => { - const bootstrap = queryClient.getQueryData( - bootstrapQueryOptions().queryKey, - ); - - const domain = bootstrap?.domains.job || "rivet-job.local"; - - return value.endsWith(`.${domain}`); - }, - () => { - const bootstrap = queryClient.getQueryData( - bootstrapQueryOptions().queryKey, - ); - - const domain = bootstrap?.domains.job || "rivet-job.local"; - return { - message: `Hostname must end with .${domain}`, - }; - }, - ), - path: z - .string() - .refine((value) => { - const regex = /^(\/[a-zA-Z0-9-_]+)*$/; - return regex.test(value); - }, "Path must start with a / and contain only alphanumeric characters, dashes, and underscores") - .refine((value) => { - const endsWithSlash = value.endsWith("/"); - return !endsWithSlash; - }, "Path must not end with a /"), - tags: z - .array( - z.object({ - key: z.string().min(1), - value: z.string(), - }), - ) - .min(1, "At least one selector is required") - .superRefine((tags, ctx) => { - const tagsSet = new Set(); - for (const [idx, tag] of [...tags].reverse().entries()) { - if (tagsSet.has(tag.key)) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - path: [idx, "key"], - message: "Tag keys must be unique", - }); - } - tagsSet.add(tag.key); - } - }), -}); - -export type FormValues = z.infer; -export type SubmitHandler = ( - values: FormValues, - form: UseFormReturn, -) => Promise; - -const { Form, Submit } = createSchemaForm(formSchema); -export { Form, Submit }; - -export const Hostname = () => { - const { control } = useFormContext(); - return ( - ( - - Hostname - - - - - - )} - /> - ); -}; - -export const Path = () => { - const { control } = useFormContext(); - - return ( - ( - - Path - - - - - - - - - )} - /> - ); -}; - -const PathMessage = () => { - const { watch } = useFormContext(); - - const path = watch("path"); - - return path.endsWith("/*") ? ( - Maximum of 8 path components when routing path prefixes. - ) : null; -}; - -export const Tags = ({ - onCreateKeyOption, - onCreateValueOption, - keys, - values, -}: { - onCreateKeyOption: (option: string) => void; - onCreateValueOption: (option: string) => void; - keys: ComboboxOption[]; - values: ComboboxOption[]; -}) => { - const { control, setValue, watch } = useFormContext(); - const { fields, append, remove } = useFieldArray({ - name: "tags", - control, - }); - - return ( - <> - {fields.length === 0 ? ( -
-

There's no selectors added.

- ( - - - - )} - /> -
- ) : null} - {fields.map((field, index) => ( -
- - - Key - - { - setValue(`tags.${index}.key`, value, { - shouldDirty: true, - shouldTouch: true, - shouldValidate: true, - }); - }} - allowCreate - onCreateOption={onCreateKeyOption} - /> - - - - - - - - Value - - { - setValue(`tags.${index}.value`, value, { - shouldDirty: true, - shouldTouch: true, - shouldValidate: true, - }); - }} - allowCreate - onCreateOption={onCreateValueOption} - /> - - - - - -
- ))} - - - ); -}; - -export const StripPrefix = () => { - const { control } = useFormContext(); - - return ( - ( - - - - - - {/* biome-ignore lint/a11y/noLabelWithoutControl: injected by FromLabel */} - - - - )} - /> - ); -}; - -export const RouteSubpaths = () => { - const { control } = useFormContext(); - - return ( - ( - - - - - - {/* biome-ignore lint/a11y/noLabelWithoutControl: injected by FromLabel */} - - - - )} - /> - ); -}; diff --git a/frontend/apps/hub/src/domains/project/helpers/backend-env-compute-diff-variables.tsx b/frontend/apps/hub/src/domains/project/helpers/backend-env-compute-diff-variables.tsx deleted file mode 100644 index 9f45b4d6e0..0000000000 --- a/frontend/apps/hub/src/domains/project/helpers/backend-env-compute-diff-variables.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import type { Rivet as RivetEe } from "@rivet-gg/api-ee"; - -type NewVariable = { key: string; value: string; isSecret: boolean }; - -export function computeBackendEnvVariablesDiff( - existingVariables: Record, - newVariables: NewVariable[], -) { - const update: NewVariable[] = []; - const create: NewVariable[] = []; - const errors: { idx: number; error: string }[] = []; - const remove: string[] = []; - - const existingVariableKeys = Object.keys(existingVariables); - - for (const [idx, variable] of newVariables.entries()) { - if (existingVariableKeys.includes(variable.key)) { - // Update the variable - if (variable.value.length > 1) { - update.push(variable); - } - } else { - if (variable.key.length < 1) { - errors.push({ - idx, - error: "Key must be at least 1 character long", - }); - } else { - // Create variable - create.push(variable); - } - } - } - - for (const existingVariableKey of existingVariableKeys) { - if (!newVariables.find((u) => u.key === existingVariableKey)) { - // Remove the user - remove.push(existingVariableKey); - } - } - - const finalVariables: Record = - {}; - for (const variable of [...create, ...update]) { - finalVariables[variable.key] = variable.isSecret - ? { secret: variable.value } - : { text: variable.value }; - } - for (const variable of remove) { - finalVariables[variable] = { delete: true }; - } - - return { variables: finalVariables, errors }; -} diff --git a/frontend/apps/hub/src/domains/project/helpers/extract-postgress-credentials.ts b/frontend/apps/hub/src/domains/project/helpers/extract-postgress-credentials.ts deleted file mode 100644 index cc0d8caa80..0000000000 --- a/frontend/apps/hub/src/domains/project/helpers/extract-postgress-credentials.ts +++ /dev/null @@ -1,12 +0,0 @@ -export const extractPostgressCredentials = (connectionString: string) => { - const regex = /postgres:\/\/([^:]+):([^@]+)@([^/]+)\/([^?]+)/; - const match = connectionString.match(regex); - if (!match) { - return null; - } - const [, user, password, host, database] = match; - const port = "5432"; // Assuming default port is 5432 for PostgreSQL - const type = "postgres"; - - return { type, port, host, user, password, database }; -}; diff --git a/frontend/apps/hub/src/domains/project/helpers/try-create-backend.ts b/frontend/apps/hub/src/domains/project/helpers/try-create-backend.ts deleted file mode 100644 index a7482e3b5e..0000000000 --- a/frontend/apps/hub/src/domains/project/helpers/try-create-backend.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { bootstrapQueryOptions } from "@/domains/auth/queries/bootstrap"; -import { isRivetError } from "@/lib/utils"; -import { rivetEeClient } from "@/queries/global"; -import type { QueryClient } from "@tanstack/react-query"; -import { projectBackendQueryOptions } from "../queries"; - -export async function tryCreateBackend({ - projectId, - environmentId, - queryClient, -}: { - projectId: string; - environmentId: string; - queryClient: QueryClient; -}) { - const { cluster } = await queryClient.fetchQuery(bootstrapQueryOptions()); - - if (cluster === "oss") { - return; - } - - try { - await queryClient.fetchQuery( - projectBackendQueryOptions({ projectId, environmentId }), - ); - } catch (error) { - if (isRivetError(error)) { - if (error.body.code === "BACKEND_NOT_FOUND") { - await rivetEeClient.ee.backend.create( - projectId, - environmentId, - {}, - ); - await queryClient.invalidateQueries({ - ...projectBackendQueryOptions({ projectId, environmentId }), - refetchType: "all", - }); - return; - } - } - } - return; -} diff --git a/frontend/apps/hub/src/domains/project/hooks/use-cdn-manage-auth-users-form-handler.tsx b/frontend/apps/hub/src/domains/project/hooks/use-cdn-manage-auth-users-form-handler.tsx deleted file mode 100644 index 3a21978130..0000000000 --- a/frontend/apps/hub/src/domains/project/hooks/use-cdn-manage-auth-users-form-handler.tsx +++ /dev/null @@ -1,120 +0,0 @@ -import type { SubmitHandler } from "@/domains/project/forms/cdn-manage-auth-users-form"; -import { queryClient } from "@/queries/global"; -import type { Rivet } from "@rivet-gg/api-full"; -import bcrypt from "bcryptjs"; -import { useCallback } from "react"; -import { - projectEnvironmentQueryOptions, - projectQueryOptions, - useEnvironmentRemoveCdnAuthUserMutation, - useEnvironmentUpdateCdnAuthUserMutation, -} from "../queries"; - -const SALT = bcrypt.genSaltSync(10); - -type CdnEnvironmentAuthPasswordUser = Pick< - Rivet.cloud.CdnNamespaceAuthUser, - "user" -> & { - password: string; -}; - -function computeUsersDiff( - existingUsers: Rivet.cloud.CdnNamespaceAuthUser["user"][], - newUsers: CdnEnvironmentAuthPasswordUser[], -) { - const update: CdnEnvironmentAuthPasswordUser[] = []; - const create: CdnEnvironmentAuthPasswordUser[] = []; - const errors: { idx: number; error: string }[] = []; - const remove: Rivet.cloud.CdnNamespaceAuthUser["user"][] = []; - - for (const [idx, user] of newUsers.entries()) { - if (existingUsers.includes(user.user)) { - // Update the user - if (user.password.length > 1) { - update.push(user); - } - } else { - if (user.password.length < 1) { - errors.push({ - idx, - error: "Password must be at least 1 character long", - }); - } else { - // Create the user - create.push(user); - } - } - } - - for (const user of existingUsers) { - if (!newUsers.find((u) => u.user === user)) { - // Remove the user - remove.push(user); - } - } - - return { update, create, errors, remove }; -} - -interface UseCdnManageAuthUsersFormHandlerProps { - projectId: string; - environmentId: string; - userList: Rivet.cloud.CdnNamespaceAuthUser[]; - onSuccess?: () => void; -} - -export function useCdnManageAuthUsersFormHandler({ - onSuccess, - projectId, - userList, - environmentId, -}: UseCdnManageAuthUsersFormHandlerProps) { - const { mutateAsync: updateUser } = - useEnvironmentUpdateCdnAuthUserMutation(); - const { mutateAsync: removeUser } = - useEnvironmentRemoveCdnAuthUserMutation(); - - return useCallback( - async (values, form) => { - const diff = computeUsersDiff( - userList.map((user) => user.user), - values.users, - ); - if (diff.errors.length > 0) { - for (const { idx, error } of diff.errors) { - form.setError(`users.${idx}.password`, { - type: "manual", - message: error, - }); - } - return; - } - - await Promise.all([ - ...[...diff.update, ...diff.create].map((user) => - updateUser({ - projectId, - environmentId, - user: user.user, - password: bcrypt.hashSync(user.password, SALT), - }), - ), - ...diff.remove.map((user) => - removeUser({ - projectId, - environmentId, - user, - }), - ), - ]); - - await queryClient.invalidateQueries(projectQueryOptions(projectId)); - await queryClient.invalidateQueries( - projectEnvironmentQueryOptions({ projectId, environmentId }), - ); - onSuccess?.(); - }, - [projectId, environmentId, onSuccess, removeUser, updateUser, userList], - ); -} diff --git a/frontend/apps/hub/src/domains/project/hooks/use-cdn-new-custom-domain-form-handler.tsx b/frontend/apps/hub/src/domains/project/hooks/use-cdn-new-custom-domain-form-handler.tsx deleted file mode 100644 index 5621ea6312..0000000000 --- a/frontend/apps/hub/src/domains/project/hooks/use-cdn-new-custom-domain-form-handler.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import type { SubmitHandler } from "@/domains/project/forms/cdn-new-custom-domain-form"; -import { isRivetError } from "@/lib/utils"; -import { queryClient } from "@/queries/global"; -import { useCallback } from "react"; -import { - projectEnvironmentQueryOptions, - projectQueryOptions, - useEnvironmentAddDomainMutation, -} from "../queries"; - -interface UseCdnManageAuthUsersProps { - projectId: string; - environmentId: string; - onSuccess?: () => void; -} - -export function useCdnNewCustomDomainFormHandler({ - onSuccess, - projectId, - environmentId, -}: UseCdnManageAuthUsersProps) { - const { mutateAsync } = useEnvironmentAddDomainMutation(); - - return useCallback( - async (values, form) => { - try { - await mutateAsync({ - projectId, - environmentId, - domain: values.name, - }); - } catch (error) { - if (isRivetError(error)) { - return form.setError("name", { - type: "manual", - message: error.body.message, - }); - } - return form.setError("name", { - type: "manual", - message: "Invalid domain name.", - }); - } - await queryClient.invalidateQueries(projectQueryOptions(projectId)); - await queryClient.invalidateQueries( - projectEnvironmentQueryOptions({ projectId, environmentId }), - ); - onSuccess?.(); - }, - [projectId, mutateAsync, environmentId, onSuccess], - ); -} diff --git a/frontend/apps/hub/src/domains/project/hooks/use-matchmaker-lobby-config-form-handler.tsx b/frontend/apps/hub/src/domains/project/hooks/use-matchmaker-lobby-config-form-handler.tsx deleted file mode 100644 index debae92d9e..0000000000 --- a/frontend/apps/hub/src/domains/project/hooks/use-matchmaker-lobby-config-form-handler.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import type { SubmitHandler } from "@/domains/project/forms/matchmaker-lobby-config-form"; -import { validateAgainstApi } from "@/lib/async-validation"; -import { rivetClient } from "@/queries/global"; -import { useCallback } from "react"; -import { useEnvironmentMatchmakerUpdateConfigMutation } from "../queries"; - -interface UseMatchmakerLobbyConfigFormHandlerProps { - projectId: string; - environmentId: string; -} - -export function useMatchmakerLobbyConfigFormHandler({ - projectId, - environmentId, -}: UseMatchmakerLobbyConfigFormHandlerProps) { - const { mutateAsync } = useEnvironmentMatchmakerUpdateConfigMutation(); - - return useCallback( - async (values, form) => { - const res = - await rivetClient.cloud.games.namespaces.validateGameNamespaceMatchmakerConfig( - projectId, - environmentId, - values, - ); - - const { isValid } = validateAgainstApi({ - group: "GAME_NAMESPACE_CONFIG", - errors: res.errors, - }).setFormErrors(form, { - lobbyCountMax: "lobby-count", - maxPlayers: "max-players", - }); - - if (!isValid) return; - - try { - await mutateAsync({ ...values, environmentId, projectId }); - } catch { - form.setError("lobbyCountMax", { - type: "manual", - message: "An error occurred while saving the config", - }); - } - }, - [projectId, mutateAsync, environmentId], - ); -} diff --git a/frontend/apps/hub/src/domains/project/layouts/backend-layout.tsx b/frontend/apps/hub/src/domains/project/layouts/backend-layout.tsx deleted file mode 100644 index e02d7582b0..0000000000 --- a/frontend/apps/hub/src/domains/project/layouts/backend-layout.tsx +++ /dev/null @@ -1,144 +0,0 @@ -import { - Flex, - SidebarNavigation, - SidebarPageContent, - Skeleton, - cn, -} from "@rivet-gg/components"; -import { Icon, faSpinnerThird } from "@rivet-gg/icons"; -import { Link, type LinkOptions } from "@tanstack/react-router"; -import type { ComponentProps, PropsWithChildren, ReactNode } from "react"; -import { BackendEnvironmentDatabaseLink } from "../components/backend/backend-environment-database-link"; - -const LINKS = [ - { - to: "/projects/$projectNameId/environments/$environmentNameId/backend", - text: "Overview", - exact: true, - }, - { - to: "/projects/$projectNameId/environments/$environmentNameId/backend/logs", - text: "Logs", - }, - { - to: "/projects/$projectNameId/environments/$environmentNameId/backend/variables", - text: "Variables", - }, -] satisfies ({ text: string; exact?: boolean } & LinkOptions)[]; - -const DatabaseLink = ({ - isLoading, - onClick, -}: ComponentProps<"button"> & { isLoading?: boolean }) => { - return ( - - ); -}; - -interface BackendPageProps { - projectId: string; - projectNameId: string; - environmentId: string; - environmentNameId: string; - children: ReactNode; -} - -function BackendPage({ - environmentNameId, - environmentId, - projectId, - projectNameId, - children, -}: BackendPageProps) { - return ( - - {LINKS.map((link) => ( - - {link.text} - - ))} - - - - - } - > - - {children} - - - ); -} - -BackendPage.Skeleton = function BackendPageSkeleton() { - return ( - - - - - - - } - > - - - - - - ); -}; - -function Content({ children }: PropsWithChildren) { - return children; -} - -Content.Skeleton = function ContentSkeleton() { - return ( - <> - - - - ); -}; - -export { BackendPage as Root, Content }; diff --git a/frontend/apps/hub/src/domains/project/layouts/group-layout.tsx b/frontend/apps/hub/src/domains/project/layouts/group-layout.tsx deleted file mode 100644 index 91552170e4..0000000000 --- a/frontend/apps/hub/src/domains/project/layouts/group-layout.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { Page, Skeleton } from "@rivet-gg/components"; -import type { PropsWithChildren, ReactNode } from "react"; - -interface GroupPageProps { - children: ReactNode; -} - -function GroupPage({ children }: GroupPageProps) { - return {children}; -} - -GroupPage.Skeleton = Page.Skeleton; - -function Content({ children }: PropsWithChildren) { - return children; -} -Content.Skeleton = () => { - return ( - <> - - - - ); -}; - -export { GroupPage as Root, Content }; diff --git a/frontend/apps/hub/src/domains/project/layouts/group-settings-layout.tsx b/frontend/apps/hub/src/domains/project/layouts/group-settings-layout.tsx deleted file mode 100644 index dd61520e1a..0000000000 --- a/frontend/apps/hub/src/domains/project/layouts/group-settings-layout.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { - SidebarNavigation, - SidebarPageContent, - Skeleton, -} from "@rivet-gg/components"; -import { Link } from "@tanstack/react-router"; -import type { ReactNode } from "react"; - -interface GroupPageProps { - groupId: string; - children: ReactNode; -} - -function GroupSettingsPage({ children, groupId }: GroupPageProps) { - return ( - - - General - - - } - > - {children} - - ); -} - -GroupSettingsPage.Skeleton = function GroupSettingsPageSkeleton() { - return ( - - - - - - - } - > - - - - ); -}; - -export { GroupSettingsPage as Root }; diff --git a/frontend/apps/hub/src/domains/project/layouts/matchmaker-layout.tsx b/frontend/apps/hub/src/domains/project/layouts/matchmaker-layout.tsx deleted file mode 100644 index 449c50e7fd..0000000000 --- a/frontend/apps/hub/src/domains/project/layouts/matchmaker-layout.tsx +++ /dev/null @@ -1,109 +0,0 @@ -import { - Flex, - SidebarNavigation, - SidebarPageContent, - Skeleton, -} from "@rivet-gg/components"; -import { Link, type LinkOptions } from "@tanstack/react-router"; -import type { PropsWithChildren, ReactNode } from "react"; - -const LINKS = [ - { - to: "/projects/$projectNameId/environments/$environmentNameId/lobbies", - text: "Lobbies", - exact: true, - }, - { - to: "/projects/$projectNameId/environments/$environmentNameId/lobbies/logs", - text: "Logs", - }, - { - to: "/projects/$projectNameId/environments/$environmentNameId/lobbies/settings", - text: "Settings", - }, -] satisfies ({ text: string; exact?: boolean } & LinkOptions)[]; - -interface MatchmakerPageProps { - projectNameId: string; - environmentNameId: string; - children: ReactNode; -} - -function MatchmakerPage({ - projectNameId, - environmentNameId, - children, -}: MatchmakerPageProps) { - return ( - - {LINKS.map((link) => ( - - {link.text} - - ))} - - } - > - - {children} - - - ); -} - -MatchmakerPage.Skeleton = function MatchmakerPageSkeleton() { - return ( - - - - - - - } - > - - - - - - ); -}; - -function Content({ children }: PropsWithChildren) { - return children; -} - -Content.Skeleton = function ContentSkeleton() { - return ( - <> - - - - ); -}; - -export { MatchmakerPage as Root, Content }; diff --git a/frontend/apps/hub/src/domains/project/layouts/project-layout.tsx b/frontend/apps/hub/src/domains/project/layouts/project-layout.tsx deleted file mode 100644 index 43ae9949f4..0000000000 --- a/frontend/apps/hub/src/domains/project/layouts/project-layout.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { computePageLayout, usePageLayout } from "@/lib/compute-page-layout"; -import { Page, Skeleton } from "@rivet-gg/components"; -import { useMatches } from "@tanstack/react-router"; -import type { PropsWithChildren, ReactNode } from "react"; - -interface ProjectPageProps { - children: ReactNode; -} - -function ProjectPage({ children }: ProjectPageProps) { - const matches = useMatches(); - return {children}; -} - -ProjectPage.Skeleton = () => { - const layout = usePageLayout(); - if (layout === "v2") { - return ( -
- -
- ); - } - - return ; -}; - -function Content({ children }: PropsWithChildren) { - return <>{children}; -} - -Content.Skeleton = function ContentSkeleton() { - return ( - <> - -
- - -
- - - - ); -}; - -function EmptyProjectPage({ children }: PropsWithChildren) { - const matches = useMatches(); - return {children}; -} - -export { ProjectPage as Root, EmptyProjectPage as EmptyRoot, Content }; diff --git a/frontend/apps/hub/src/domains/project/layouts/project-settings-layout.tsx b/frontend/apps/hub/src/domains/project/layouts/project-settings-layout.tsx deleted file mode 100644 index 4ee73b8d29..0000000000 --- a/frontend/apps/hub/src/domains/project/layouts/project-settings-layout.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { SidebarNavigation, SidebarPageContent } from "@rivet-gg/components"; -import { Link } from "@tanstack/react-router"; -import type { ReactNode } from "react"; - -interface GroupPageProps { - projectNameId: string; - children: ReactNode; -} - -function GroupSettingsPage({ children, projectNameId }: GroupPageProps) { - return ( - - - Tokens - - - } - > - {children} - - ); -} - -export { GroupSettingsPage as Root }; diff --git a/frontend/apps/hub/src/domains/project/layouts/servers-layout.tsx b/frontend/apps/hub/src/domains/project/layouts/servers-layout.tsx deleted file mode 100644 index 20e92c3335..0000000000 --- a/frontend/apps/hub/src/domains/project/layouts/servers-layout.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import { - Flex, - SidebarNavigation, - SidebarPageContent, - Skeleton, -} from "@rivet-gg/components"; -import { Link, type LinkOptions } from "@tanstack/react-router"; -import type { PropsWithChildren, ReactNode } from "react"; - -const LINKS = [ - { - to: "/projects/$projectNameId/environments/$environmentNameId/servers", - text: "Servers", - exact: true, - }, - { - to: "/projects/$projectNameId/environments/$environmentNameId/builds", - text: "Builds", - }, -] satisfies ({ text: string; exact?: boolean } & LinkOptions)[]; - -interface ServersPageProps { - projectNameId: string; - environmentNameId: string; - children: ReactNode; -} - -function ServersPage({ - projectNameId, - environmentNameId, - children, -}: ServersPageProps) { - return ( - - {LINKS.map((link) => ( - - {link.text} - - ))} - - } - > - - {children} - - - ); -} - -ServersPage.Skeleton = function ServersPageSkeleton() { - return ( - - - - - - - } - > - - - - - - ); -}; - -function Content({ children }: PropsWithChildren) { - return children; -} - -Content.Skeleton = function ContentSkeleton() { - return ( - <> - - - - ); -}; - -export { ServersPage as Root, Content }; diff --git a/frontend/apps/hub/src/domains/project/queries/actors/mutations.ts b/frontend/apps/hub/src/domains/project/queries/actors/mutations.ts deleted file mode 100644 index a8048e0acd..0000000000 --- a/frontend/apps/hub/src/domains/project/queries/actors/mutations.ts +++ /dev/null @@ -1,335 +0,0 @@ -import { mutationOptions, queryClient, rivetClient } from "@/queries/global"; -import type { Rivet } from "@rivet-gg/api-full"; -import { toast } from "@rivet-gg/components"; -import { useMutation } from "@tanstack/react-query"; -import { customAlphabet } from "nanoid"; -import { - actorBuildsQueryOptions, - actorQueryOptions, - projectActorsQueryOptions, - routesQueryOptions, -} from "./query-options"; - -const nanoid = customAlphabet("0123456789abcdefghijklmnoprstwuxyz", 5); - -export function destroyActorMutationOptions() { - return mutationOptions({ - mutationFn: (opts: { - projectNameId: string; - environmentNameId: string; - actorId: string; - }) => - rivetClient.actors.destroy(opts.actorId, { - environment: opts.environmentNameId, - project: opts.projectNameId, - }), - onSuccess: async (_, { projectNameId, environmentNameId, actorId }) => { - const { queryKey: projectActorsQueryKey } = - projectActorsQueryOptions({ - projectNameId: "", - environmentNameId: "", - }); - - await queryClient.invalidateQueries( - actorQueryOptions({ - projectNameId, - environmentNameId, - actorId, - }), - ); - await queryClient.invalidateQueries({ - predicate: (query) => { - return query.queryKey.every((key, i) => { - return ( - projectActorsQueryKey[i] === key || - projectActorsQueryKey[i] === "" - ); - }); - }, - refetchType: "all", - }); - }, - }); -} - -export function usePatchActorBuildTagsMutation({ - onSuccess, -}: { onSuccess?: () => void } = {}) { - return useMutation({ - mutationFn: async ({ - projectNameId, - environmentNameId, - buildId, - ...request - }: { - projectNameId: string; - environmentNameId: string; - buildId: string; - } & Rivet.servers.PatchBuildTagsRequest) => { - // TODO: Cache this - // Get original build - const ogBuild = await rivetClient.builds.get(buildId, { - project: projectNameId, - environment: environmentNameId, - }); - - // If setting build to current, remove current tag from all other builds with the same name - if ( - ogBuild.build.tags.name && - (request.tags as Record | undefined) - ?.current === "true" - ) { - const currentBuilds = await rivetClient.builds.list({ - project: projectNameId, - environment: environmentNameId, - tagsJson: JSON.stringify({ - name: ogBuild.build.tags.name, - current: "true", - }), - }); - - for (const build of currentBuilds.builds) { - await rivetClient.builds.patchTags(build.id, { - project: projectNameId, - environment: environmentNameId, - body: { - tags: { - current: null, - }, - }, - }); - } - } - - // Update tags - return await rivetClient.builds.patchTags(buildId, { - project: projectNameId, - environment: environmentNameId, - body: request, - }); - }, - onSuccess: async (_, { projectNameId, environmentNameId, buildId }) => { - await Promise.all([ - queryClient.invalidateQueries( - projectActorsQueryOptions({ - projectNameId, - environmentNameId, - }), - ), - // until we migrate old endpoints to use nameIds - queryClient.invalidateQueries({ - predicate(query) { - return ( - query.queryKey[0] === "project" && - query.queryKey[2] === "environment" && - query.queryKey[4] === "builds" - ); - }, - }), - ]); - onSuccess?.(); - }, - }); -} - -export function useUpgradeAllActorsMutation({ - onSuccess, -}: { onSuccess?: () => void } = {}) { - return useMutation({ - mutationFn: ({ - projectNameId, - environmentNameId, - ...request - }: { - projectNameId: string; - environmentNameId: string; - } & Rivet.actors.UpgradeAllActorsRequest) => - rivetClient.actors.upgradeAll({ - project: projectNameId, - environment: environmentNameId, - body: request, - }), - onSuccess: async (response, { projectNameId, environmentNameId }) => { - await Promise.allSettled([ - queryClient.invalidateQueries( - projectActorsQueryOptions({ - projectNameId, - environmentNameId, - }), - ), - queryClient.invalidateQueries( - actorBuildsQueryOptions({ - projectNameId, - environmentNameId, - }), - ), - ]); - - toast.success( - response.count - ? `Build successfully tagged. Upgraded ${response.count} actors to the latest build.` - : "Build successfully tagged. No actors to upgrade.", - ); - onSuccess?.(); - }, - }); -} - -export function useCreateActorFromSdkMutation({ - onSuccess, -}: { onSuccess?: () => void }) { - return useMutation({ - mutationFn: async ({ - projectNameId, - environmentNameId, - buildId, - region, - parameters, - }: { - projectNameId: string; - environmentNameId: string; - buildId: string; - region: string; - parameters: unknown; - }) => { - // const managerUrl = await queryClient.fetchQuery( - // actorManagerUrlQueryOptions({ - // projectNameId, - // environmentNameId, - // }), - // ); - // const { build } = await queryClient.fetchQuery( - // actorBuildQueryOptions({ - // projectNameId, - // environmentNameId, - // buildId, - // }), - // ); - // const cl = new Client(managerUrl); - // await cl.create({ - // parameters, - // create: { tags: { name: build.tags.name || build.id }, region }, - // }); - }, - onSuccess: async () => { - await queryClient.invalidateQueries({ - predicate(query) { - return ( - query.queryKey[0] === "project" && - query.queryKey[2] === "environment" && - query.queryKey[4] === "actors" - ); - }, - }); - onSuccess?.(); - }, - }); -} - -export const usePatchRouteMutation = ({ - onSuccess, -}: { onSuccess?: () => void } = {}) => { - return useMutation({ - mutationFn: async ({ - projectNameId, - environmentNameId, - id, - ...request - }: { - projectNameId: string; - environmentNameId: string; - id: string; - } & Rivet.routes.UpdateRouteBody) => - rivetClient.routes.update(id, { - body: request, - project: projectNameId, - environment: environmentNameId, - }), - onSuccess: async (_, { projectNameId, environmentNameId }) => { - await queryClient.invalidateQueries( - routesQueryOptions({ - projectNameId, - environmentNameId, - }), - ); - onSuccess?.(); - }, - }); -}; - -export const useCreateRouteMutation = ({ - onSuccess, -}: { onSuccess?: () => void } = {}) => { - return useMutation({ - mutationFn: async ({ - projectNameId, - environmentNameId, - ...request - }: { - projectNameId: string; - environmentNameId: string; - } & Rivet.routes.UpdateRouteBody) => - rivetClient.routes.update(`route-${nanoid()}`, { - body: request, - project: projectNameId, - environment: environmentNameId, - }), - onSuccess: async (_, { projectNameId, environmentNameId }) => { - await queryClient.invalidateQueries( - routesQueryOptions({ - projectNameId, - environmentNameId, - }), - ); - onSuccess?.(); - }, - }); -}; - -export const useDeleteRouteMutation = ({ - onSuccess, -}: { onSuccess?: () => void } = {}) => { - return useMutation({ - mutationFn: async ({ - projectNameId, - environmentNameId, - routeId, - }: { - projectNameId: string; - environmentNameId: string; - routeId: string; - }) => - rivetClient.routes.delete(routeId, { - project: projectNameId, - environment: environmentNameId, - }), - onSuccess: async (_, { projectNameId, environmentNameId }) => { - await queryClient.invalidateQueries( - routesQueryOptions({ - projectNameId, - environmentNameId, - }), - ); - onSuccess?.(); - }, - }); -}; - -export const useExportActorLogsMutation = () => { - return useMutation({ - mutationFn: async ({ - projectNameId, - environmentNameId, - queryJson, - }: { - projectNameId: string; - environmentNameId: string; - queryJson: string; - }) => - rivetClient.actors.logs.export({ - project: projectNameId, - environment: environmentNameId, - queryJson, - }), - }); -}; diff --git a/frontend/apps/hub/src/domains/project/queries/actors/query-options.ts b/frontend/apps/hub/src/domains/project/queries/actors/query-options.ts deleted file mode 100644 index 37771832fe..0000000000 --- a/frontend/apps/hub/src/domains/project/queries/actors/query-options.ts +++ /dev/null @@ -1,861 +0,0 @@ -import { mergeWatchStreams } from "@/lib/watch-utilities"; -import { rivetClient } from "@/queries/global"; -import { getMetaWatchIndex } from "@/queries/utils"; -import type { Rivet } from "@rivet-gg/api-full"; -import { type LogFmtValue, logfmt, safe, toRecord } from "@rivet-gg/components"; -import { getActorStatus } from "@rivet-gg/components/actors"; -import { - type InfiniteData, - infiniteQueryOptions, - keepPreviousData, - queryOptions, -} from "@tanstack/react-query"; -import stripAnsi from "strip-ansi"; - -export const projectActorsQueryOptions = ({ - projectNameId, - environmentNameId, - includeDestroyed, - tags, -}: { - projectNameId: string; - environmentNameId: string; - includeDestroyed?: boolean; - tags?: Record; -}) => { - return infiniteQueryOptions({ - queryKey: [ - "project", - projectNameId, - "environment", - environmentNameId, - "actors", - { includeDestroyed, tags }, - ] as const, - refetchInterval: 5000, - staleTime: 0, - gcTime: 0, - initialPageParam: "", - queryFn: ({ - signal: abortSignal, - pageParam, - queryKey: [, project, , environment, , { includeDestroyed, tags }], - }) => - rivetClient.actors.list( - { - project, - environment, - includeDestroyed, - cursor: pageParam ? pageParam : undefined, - tagsJson: JSON.stringify(tags), - }, - { abortSignal }, - ), - select: (data) => data.pages.flatMap((page) => page.actors || []), - getNextPageParam: (lastPage) => { - return lastPage.pagination.cursor; - }, - meta: { - updateCache: ( - data: InfiniteData, - client, - ) => { - for (const page of data.pages) { - for (const actor of page.actors) { - client.setQueryData( - [ - "project", - projectNameId, - "environment", - environmentNameId, - "actor", - actor.id, - ], - (oldData) => { - if (!oldData) return oldData; - return { - actor, - }; - }, - ); - } - } - }, - }, - }); -}; - -export const actorsCountQueryOptions = ({ - projectNameId, - environmentNameId, - includeDestroyed, - tags, -}: { - projectNameId: string; - environmentNameId: string; - includeDestroyed?: boolean; - tags?: Record; -}) => { - return infiniteQueryOptions({ - ...projectActorsQueryOptions({ - projectNameId, - environmentNameId, - tags, - includeDestroyed, - }), - select: (data) => - data.pages.flatMap((page) => page.actors || []).length, - notifyOnChangeProps: ["data"], - }); -}; - -export const actorQueryOptions = ({ - projectNameId, - environmentNameId, - actorId, -}: { - projectNameId: string; - environmentNameId: string; - actorId: string; -}) => { - return queryOptions({ - queryKey: [ - "project", - projectNameId, - "environment", - environmentNameId, - "actor", - actorId, - ], - queryFn: ({ - signal: abortSignal, - queryKey: [_, project, __, environment, ___, actorId], - }) => - rivetClient.actors.get( - actorId, - { project, environment }, - { - abortSignal, - }, - ), - select: (data) => ({ - ...data.actor, - createTs: data.actor.createdAt - ? new Date(data.actor.createdAt) - : new Date(), - startTs: data.actor.startedAt - ? new Date(data.actor.startedAt) - : undefined, - destroyTs: data.actor.destroyedAt - ? new Date(data.actor.destroyedAt) - : undefined, - runtime: { - ...data.actor.runtime, - arguments: data.actor.runtime.arguments?.filter( - (arg) => arg !== "", - ), - }, - tags: data.actor.tags as Record, - endpoint: createActorEndpoint(data.actor.network), - }), - }); -}; - -export const actorStatusQueryOptions = ({ - projectNameId, - environmentNameId, - actorId, -}: { - projectNameId: string; - environmentNameId: string; - actorId: string; -}) => { - return queryOptions({ - ...actorQueryOptions({ projectNameId, environmentNameId, actorId }), - select: (data) => getActorStatus(data.actor), - }); -}; - -export const actorDestroyedAtQueryOptions = ({ - projectNameId, - environmentNameId, - actorId, -}: { - projectNameId: string; - environmentNameId: string; - actorId: string; -}) => - queryOptions({ - ...actorQueryOptions({ projectNameId, environmentNameId, actorId }), - select: (data) => - data.actor.destroyedAt - ? new Date(data.actor.destroyedAt) - : undefined, - }); - -export const actorLogsQueryOptions = ( - { - projectNameId, - environmentNameId, - actorId, - }: { - projectNameId: string; - environmentNameId: string; - actorId: string; - }, - opts: { refetchInterval?: number } = {}, -) => { - return queryOptions({ - ...opts, - queryKey: [ - "project", - projectNameId, - "environment", - environmentNameId, - "actor", - actorId, - "logs", - ] as const, - queryFn: async ({ - signal: abortSignal, - meta, - queryKey: [, project, , environment, , actorId], - }) => { - const response = await rivetClient.actors.logs.get( - { - project, - environment, - queryJson: JSON.stringify({ - string_equal: { - property: "actor_id", - value: actorId, - }, - }), - watchIndex: getMetaWatchIndex(meta), - }, - { abortSignal }, - ); - - const logs = response.lines.map((line, idx) => { - const timestamp = response.timestamps[idx]; - const stream = response.streams[idx]; - const raw = stripAnsi(window.atob(line)); - return { - id: `${actorId}-${timestamp}-${idx}`, - level: stream === 1 ? "error" : "info", - timestamp, - line: raw, - message: "", - properties: {}, - } as const; - }); - - return { ...response, logs }; - }, - meta: { - watch: mergeWatchStreams, - }, - }); -}; - -export const actorMetricsQueryOptions = ( - { - projectNameId, - environmentNameId, - actorId, - timeWindowMs, - }: { - projectNameId: string; - environmentNameId: string; - actorId: string; - timeWindowMs?: number; - }, - opts: { refetchInterval?: number } = {}, -) => { - return queryOptions({ - ...opts, - queryKey: [ - "project", - projectNameId, - "environment", - environmentNameId, - "actor", - actorId, - "metrics", - timeWindowMs, - ] as const, - queryFn: async ({ - signal: abortSignal, - queryKey: [, project, , environment, , actorId, , timeWindowMs], - }) => { - const now = Date.now(); - const lookbackMs = timeWindowMs || 15 * 60 * 1000; // Default to 15 minutes - // Calculate interval to target approximately 60 datapoints - const targetDatapoints = 60; - const dataInterval = Math.max(15_000, Math.floor(lookbackMs / targetDatapoints)); // Minimum 15 seconds - const response = await rivetClient.actors.metrics.get( - actorId, - { - project, - environment, - start: now - lookbackMs, - end: now, - interval: dataInterval, - }, - { abortSignal }, - ); - - // Process the new response format - const metrics: Record = {}; - const rawData: Record = {}; - - if ( - response.metricNames && - response.metricValues && - response.metricAttributes && - response.metricNames.length > 0 - ) { - response.metricNames.forEach((metricName, index) => { - const metricValues = response.metricValues[index]; - const attributes = response.metricAttributes[index] || {}; - - // Create the metric key based on the metric name and attributes - let metricKey = metricName; - - // Handle specific attribute mappings to match UI expectations - if (attributes.failure_type && attributes.scope) { - metricKey = `memory_failures_${attributes.failure_type}_${attributes.scope}`; - } else if (attributes.tcp_state) { - if (metricName.includes("tcp6")) { - metricKey = `network_tcp6_usage_${attributes.tcp_state}`; - } else { - metricKey = `network_tcp_usage_${attributes.tcp_state}`; - } - } else if (attributes.udp_state) { - if (metricName.includes("udp6")) { - metricKey = `network_udp6_usage_${attributes.udp_state}`; - } else { - metricKey = `network_udp_usage_${attributes.udp_state}`; - } - } else if (attributes.state) { - metricKey = `tasks_state_${attributes.state}`; - } else if (attributes.interface) { - // Handle network interface attributes - const baseMetric = metricName.replace( - /^container_/, - "", - ); - metricKey = `${baseMetric}_${attributes.interface}`; - } else if (attributes.device) { - // Handle filesystem device attributes - const baseMetric = metricName.replace( - /^container_/, - "", - ); - metricKey = `${baseMetric}_${attributes.device}`; - } else { - // Remove "container_" prefix to match UI expectations - metricKey = metricName.replace(/^container_/, ""); - } - - // Store raw time series data for rate calculations - rawData[metricKey] = metricValues || []; - - if (metricValues && metricValues.length > 0) { - // Get the latest non-zero value (last value is often 0) - let value = null; - for (let i = metricValues.length - 1; i >= 0; i--) { - if (metricValues[i] !== 0) { - value = metricValues[i]; - break; - } - } - // If all values are 0, use the last value anyway - if (value === null && metricValues.length > 0) { - value = metricValues[metricValues.length - 1]; - } - metrics[metricKey] = value; - } else { - metrics[metricKey] = null; - } - }); - } - - return { - metrics, - rawData, - interval: dataInterval, - }; - }, - }); -}; - -export const actorBuildsQueryOptions = ({ - projectNameId, - environmentNameId, - tags = {}, -}: { - projectNameId: string; - environmentNameId: string; - tags?: Record; -}) => { - return queryOptions({ - queryKey: [ - "project", - projectNameId, - "environment", - environmentNameId, - "actor-builds", - tags, - ] as const, - refetchInterval: 2000, - queryFn: ({ - queryKey: [, project, , environment, , tagsJson], - signal: abortSignal, - }) => - rivetClient.builds.list( - { project, environment, tagsJson: JSON.stringify(tagsJson) }, - { - abortSignal, - }, - ), - select: (data) => data.builds, - }); -}; - -export const actorBuildTagsQueryOptions = ({ - projectId, - environmentId, -}: { - projectId: string; - environmentId: string; -}) => { - return queryOptions({ - queryKey: [ - "project", - projectId, - "environment", - environmentId, - "builds", - {}, - "all", - ] as const, - queryFn: async ({ - queryKey: [_, projectId, __, environmentId, ___, tags], - signal: abortSignal, - }) => { - const response = await rivetClient.servers.builds.list( - projectId, - environmentId, - { tagsJson: JSON.stringify({}) }, - { - abortSignal, - }, - ); - - return response.builds.flatMap((build) => - Object.entries(build.tags).map(([key, value]) => ({ - key, - value, - })), - ); - }, - structuralSharing(oldData, newData) { - const response = - (newData as { key: string; value: string }[]) || []; - - const tags = new Map>(); - - if (oldData && Array.isArray(oldData)) { - for (const build of oldData) { - for (const [key, value] of Object.entries(build.tags)) { - if (!tags.has(key)) { - tags.set(key, new Set()); - } - if (typeof value === "string") { - tags.get(key)?.add(value); - } - } - } - } - - for (const { key, value } of response) { - if (!tags.has(key)) { - tags.set(key, new Set()); - } - tags.get(key)?.add(value); - } - - const allTags = [...tags.entries()].flatMap(([key, values]) => - [...values.values()].map((value) => ({ - key, - value, - })), - ); - - return allTags; - }, - }); -}; - -export const actorBuildQueryOptions = ({ - projectNameId, - environmentNameId, - buildId, -}: { - projectNameId: string; - environmentNameId: string; - buildId: string; -}) => { - return queryOptions({ - queryKey: [ - "project", - projectNameId, - "environment", - environmentNameId, - "actor-build", - buildId, - ], - queryFn: ({ - signal: abortSignal, - queryKey: [_, project, __, environment, ___, build], - }) => - rivetClient.builds.get( - build, - { project, environment }, - { - abortSignal, - }, - ), - select: (data) => data.build, - }); -}; - -export const actorRegionsQueryOptions = ({ - projectNameId, - environmentNameId, -}: { projectNameId: string; environmentNameId: string }) => { - return queryOptions({ - queryKey: [ - "project", - projectNameId, - "environment", - environmentNameId, - "regions", - ], - queryFn: ({ - signal: abortSignal, - queryKey: [_, project, __, environment], - }) => - rivetClient.regions.list( - { project, environment }, - { - abortSignal, - }, - ), - select: (data) => data.regions, - }); -}; - -export const actorRegionQueryOptions = ({ - projectNameId, - environmentNameId, - regionId, -}: { - projectNameId: string; - environmentNameId: string; - regionId: string; -}) => { - return queryOptions({ - ...actorRegionsQueryOptions({ projectNameId, environmentNameId }), - select: (data) => - actorRegionsQueryOptions({ projectNameId, environmentNameId }) - .select?.(data) - .find((region) => region.id === regionId), - }); -}; - -export const createActorEndpoint = ( - network: Rivet.actors.Network, -): string | undefined => { - try { - const http = Object.values(network.ports).find( - (port) => port.protocol === "http" || port.protocol === "https", - ); - if (!http) { - return undefined; - } - // undocumented - // @ts-ignore - if (http.url) { - // undocumented - // @ts-ignore - return http.url; - } - const url = new URL(`${http.protocol}://${http.hostname}:${http.port}`); - url.pathname = http.path || "/"; - return url.href; - } catch { - return undefined; - } -}; - -export const actorManagerUrlQueryOptions = ({ - projectNameId, - environmentNameId, -}: { - projectNameId: string; - environmentNameId: string; -}) => { - return queryOptions({ - queryKey: [ - "project", - projectNameId, - "environment", - environmentNameId, - "actor-manager", - ], - queryFn: async ({ - signal: abortSignal, - queryKey: [_, project, __, environment], - }) => { - const response = await rivetClient.actors.list( - { - project, - environment, - tagsJson: JSON.stringify({ name: "manager" }), - }, - { abortSignal }, - ); - - if (response.actors.length === 0) { - throw new Error("No actor manager found"); - } - const href = createActorEndpoint(response.actors[0].network); - - if (!href) { - throw new Error("No actor manager found"); - } - - return href; - }, - }); -}; - -export const actorBuildsCountQueryOptions = ({ - projectNameId, - environmentNameId, -}: { - projectNameId: string; - environmentNameId: string; -}) => { - return queryOptions({ - ...actorBuildsQueryOptions({ projectNameId, environmentNameId }), - select: (data) => data.builds.length, - notifyOnChangeProps: ["data"], - }); -}; - -export interface FunctionInvoke { - id: string; - isFormatted: boolean; - actorId: string; - actorName: string; - actorTags: Record; - regionId: string; - timestamp: Date; - level: string; - line: string; - message: string; - properties: Record; -} - -export const logsAggregatedQueryOptions = ({ - projectNameId, - environmentNameId, - search, -}: { - projectNameId: string; - environmentNameId: string; - search?: { text?: string; caseSensitive?: boolean; enableRegex?: boolean }; -}) => { - return queryOptions({ - refetchInterval: 5000, - placeholderData: keepPreviousData, - queryKey: [ - "project", - projectNameId, - "environment", - environmentNameId, - "logs", - search, - ] as const, - queryFn: async ({ - signal: abortSignal, - client, - queryKey: [_, project, __, environment, ___, search], - }) => { - let query = undefined; - if (search?.text) { - if (search.enableRegex) { - query = { - string_match_regex: { - property: "message", - pattern: search.enableRegex, - case_insensitive: !search.enableRegex, - }, - }; - } else { - query = { - string_contains: { - property: "message", - pattern: search.enableRegex, - case_insensitive: !search.enableRegex, - }, - }; - } - } - - const logs = await rivetClient.actors.logs.get( - { - project, - environment, - queryJson: query ? JSON.stringify(query) : undefined, - }, - { - abortSignal, - }, - ); - - // Fetch all actors that appear in the logs - const actorsMap = new Map(); - - // Get unique actor IDs from logs - const uniqueActorIds = [...new Set(logs.actorIds)]; - - // Fetch actor details in parallel using TanStack Query for caching - const actorPromises = uniqueActorIds.map(async (actorId) => { - try { - // Use fetchQuery to leverage TanStack Query's caching - const data = await client.fetchQuery({ - ...actorQueryOptions({ - projectNameId: project, - environmentNameId: environment, - actorId, - }), - staleTime: 60_000, - }); - return data; - } catch (error) { - // If actor not found or error, return null - console.warn(`Failed to fetch actor ${actorId}:`, error); - return null; - } - }); - - const actors = await Promise.all(actorPromises); - - // Populate the actors map - for (const actor of actors) { - if (actor) { - actorsMap.set(actor.actor.id, actor.actor); - } - } - - const parsed = logs.lines.map((line, idx) => { - const actorIdx = logs.actorIndices[idx]; - const actorId = logs.actorIds[actorIdx]; - const timestamp = logs.timestamps[idx]; - const stream = logs.streams[idx]; - const raw = stripAnsi(window.atob(line)); - const fmt = safe(logfmt.parse)(raw)[0]; - const json = safe(JSON.parse)(raw)[0]; - const formatted = json || fmt; - const { - level = stream === 1 ? "error" : "info", - msg, - ...properties - } = formatted || {}; - const isFormatDefined = - (fmt?.level || json) && Object.keys(formatted).length > 0; - const actor = actorsMap.get(actorId); - return { - id: `${actorId}-${timestamp}-${idx}`, - level: level, - isFormatted: isFormatDefined, - actorId: actorId, - actorName: - (toRecord(actor?.tags).name as string) || - actorId.split("-")[0], - actorTags: toRecord(actor?.tags), - regionId: actor?.region || "local", - timestamp, - line: raw, - message: isFormatDefined ? (msg as string) : "", - properties: isFormatDefined ? properties : {}, - } satisfies FunctionInvoke; - }); - - return parsed.toReversed(); - }, - }); -}; - -export interface Route { - id: string; - hostname: string; - pathPrefix: string; - selector: Record; - createdAt: Date; -} - -export const routesQueryOptions = ({ - projectNameId, - environmentNameId, -}: { - projectNameId: string; - environmentNameId: string; -}) => { - return queryOptions({ - queryKey: [ - "project", - projectNameId, - "environment", - environmentNameId, - "routes", - ], - queryFn: async ({ - signal: abortSignal, - queryKey: [_, project, __, environment], - }) => { - return rivetClient.routes.list( - { - project, - environment, - }, - { abortSignal }, - ); - }, - select: (data) => data.routes, - }); -}; - -export const routeQueryOptions = ({ - projectNameId, - environmentNameId, - routeId, -}: { - projectNameId: string; - environmentNameId: string; - routeId: string; -}) => { - return queryOptions({ - ...routesQueryOptions({ - projectNameId, - environmentNameId, - }), - select: (data) => { - return data.routes.find((route) => route.id === routeId); - }, - }); -}; diff --git a/frontend/apps/hub/src/domains/project/queries/backend/helpers.ts b/frontend/apps/hub/src/domains/project/queries/backend/helpers.ts deleted file mode 100644 index d7a7bb975f..0000000000 --- a/frontend/apps/hub/src/domains/project/queries/backend/helpers.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { useQuery } from "@tanstack/react-query"; -import { useProjectBackendEnvDatabasePreviewMutation } from "./mutations"; -import { projectBackendProjectEnvDatabasePreviewQueryOptions } from "./query-options"; - -export function useEnvironmentDatabasePreview(variables: { - projectId: string; - environmentId: string; -}) { - const { isPending, mutateAsync } = - useProjectBackendEnvDatabasePreviewMutation(); - const { data: cachedData } = useQuery( - projectBackendProjectEnvDatabasePreviewQueryOptions(variables), - ); - - return { - isLoading: isPending, - data: cachedData, - mutateAsync, - }; -} diff --git a/frontend/apps/hub/src/domains/project/queries/backend/mutations.ts b/frontend/apps/hub/src/domains/project/queries/backend/mutations.ts deleted file mode 100644 index dc45851424..0000000000 --- a/frontend/apps/hub/src/domains/project/queries/backend/mutations.ts +++ /dev/null @@ -1,144 +0,0 @@ -import { useAuth } from "@/domains/auth/contexts/auth"; -import { queryClient, rivetEeClient } from "@/queries/global"; -import { OuterbaseError } from "@/queries/types"; -import type { Rivet as RivetEe } from "@rivet-gg/api-ee"; -import { getConfig, toast } from "@rivet-gg/components"; -import { useMutation, useQueryClient } from "@tanstack/react-query"; -import { usePostHog } from "posthog-js/react"; -import { extractPostgressCredentials } from "../../helpers/extract-postgress-credentials"; -import { - projectBackendEnvVariablesQueryOptions, - projectBackendProjectEnvDatabasePreviewQueryOptions, - projectBackendProjectEnvDatabaseQueryOptions, - projectBackendQueryOptions, -} from "./query-options"; -import { OuterbaseStarlinkResponse } from "./types"; - -export const useCreateBackendMutation = ({ - onSuccess, -}: { - onSuccess?: (data: RivetEe.ee.backend.CreateResponse) => void; -}) => - useMutation({ - mutationFn: ({ - projectId, - environmentId, - ...data - }: RivetEe.ee.backend.CreateRequest & { - projectId: string; - environmentId: string; - }) => rivetEeClient.ee.backend.create(projectId, environmentId, data), - onSuccess: async (data) => { - onSuccess?.(data); - }, - }); - -export const useBackendUpdateVariablesMutation = () => - useMutation({ - mutationFn: ({ - projectId, - environmentId, - ...data - }: RivetEe.ee.backend.UpdateVariablesRequest & { - projectId: string; - environmentId: string; - }) => - rivetEeClient.ee.backend.updateVariables( - projectId, - environmentId, - data, - ), - onSuccess: async (data, { projectId, environmentId }) => { - await Promise.all([ - queryClient.invalidateQueries( - projectBackendQueryOptions({ projectId, environmentId }), - ), - queryClient.invalidateQueries( - projectBackendEnvVariablesQueryOptions({ - projectId, - environmentId, - }), - ), - ]); - }, - }); - -export const useProjectBackendEnvDatabasePreviewMutation = ( - opts: { onSuccess?: (url: string) => void } = {}, -) => { - const postHog = usePostHog(); - const queryClient = useQueryClient(); - const { profile } = useAuth(); - return useMutation({ - mutationKey: ["backend-project", "env", "database-preview"], - mutationFn: async ({ - projectId, - environmentId, - }: { - projectId: string; - environmentId: string; - }) => { - const response = await queryClient.fetchQuery( - projectBackendProjectEnvDatabaseQueryOptions({ - projectId, - environmentId, - }), - ); - - if (!response.url) { - throw new Error("Database URL not found"); - } - - const credentials = extractPostgressCredentials(response.url); - - const starlinkResponse = await fetch( - "https://app.outerbase.com/api/v1/starlink", - { - method: "POST", - headers: { - "Content-Type": "application/json", - "x-provider-token": getConfig().outerbaseProviderToken, - }, - body: JSON.stringify({ - credentials: { - ...credentials, - ssl_config: { - require: true, - }, - }, - providerUniqueId: profile?.identity.identityId, - }), - }, - ); - - if (!starlinkResponse.ok) { - throw await starlinkResponse.json(); - } - - const parsedResponse = OuterbaseStarlinkResponse.parse( - await starlinkResponse.json(), - ); - return parsedResponse.response.url; - }, - onSuccess: async (data, variables) => { - await queryClient.setQueryData( - projectBackendProjectEnvDatabasePreviewQueryOptions(variables) - .queryKey, - data, - ); - opts.onSuccess?.(data); - }, - onError: (error, variables) => { - const result = OuterbaseError.safeParse(error); - if ( - result.success && - result.data.error.description === "RATE_LIMIT_EXCEEDED" - ) { - postHog.capture("outerbase_rate_limit_exceeded", variables); - return toast.error( - "Rate limit exceeded. Please try again later.", - ); - } - }, - }); -}; diff --git a/frontend/apps/hub/src/domains/project/queries/backend/query-options.ts b/frontend/apps/hub/src/domains/project/queries/backend/query-options.ts deleted file mode 100644 index da348b87a9..0000000000 --- a/frontend/apps/hub/src/domains/project/queries/backend/query-options.ts +++ /dev/null @@ -1,154 +0,0 @@ -import { mergeWatchStreams } from "@/lib/watch-utilities"; -import { rivetEeClient } from "@/queries/global"; -import { getMetaWatchIndex } from "@/queries/utils"; -import { queryOptions } from "@tanstack/react-query"; -import { z } from "zod"; -import { BackendEvent } from "./types"; - -const partialEnvLogsResponse = z - .object({ - events: z.array(z.object({}).passthrough()), - }) - .passthrough(); - -export const projectBackendQueryOptions = ({ - projectId, - environmentId, -}: { - projectId: string; - environmentId: string; -}) => - queryOptions({ - queryKey: [ - "project", - projectId, - "environment", - environmentId, - "backend", - ], - queryFn: ({ queryKey: [_, projectId, __, environmentId], signal }) => - rivetEeClient.ee.backend.get( - projectId, - environmentId, - {}, - { abortSignal: signal }, - ), - select: (data) => data.backend, - }); - -export const projectBackendEnvVariablesQueryOptions = ({ - projectId, - environmentId, -}: { - projectId: string; - environmentId: string; -}) => - queryOptions({ - queryKey: [ - "project", - projectId, - "backend-env", - environmentId, - "variables", - ], - queryFn: ({ queryKey: [_, projectId, __, environmentId], signal }) => - rivetEeClient.ee.backend.getVariables(projectId, environmentId, { - abortSignal: signal, - }), - select: (data) => data.variables, - }); - -export const projectBackendEnvEventsQueryOptions = ({ - projectId, - environmentId, -}: { - projectId: string; - environmentId: string; -}) => - queryOptions({ - queryKey: [ - "project", - projectId, - "backend-env", - environmentId, - "events", - ], - queryFn: async ({ - queryKey: [_, projectId, __, environmentId], - meta, - signal, - }) => { - const response = await rivetEeClient.ee.backend.getEvents( - projectId, - environmentId, - { watchIndex: getMetaWatchIndex(meta) }, - { abortSignal: signal }, - ); - return { - ...response, - events: z.array(BackendEvent).parse(response.events), - }; - }, - select: (data) => data.events, - meta: { - watch: mergeWatchStreams, - }, - }); - -export const projectBackendEnvEventQueryOptions = ({ - projectId, - environmentId, - eventId, -}: { - projectId: string; - environmentId: string; - eventId: string; -}) => - queryOptions({ - ...projectBackendEnvEventsQueryOptions({ projectId, environmentId }), - select: (data) => - data.events.find((event) => event.eventTimestamp === eventId), - }); - -export const projectBackendProjectEnvDatabaseQueryOptions = ({ - projectId, - environmentId, -}: { - projectId: string; - environmentId: string; -}) => - queryOptions({ - queryKey: [ - "project", - projectId, - "backend-env", - environmentId, - "database-url", - ], - queryFn: ({ queryKey: [_, projectId, __, environmentId] }) => - rivetEeClient.ee.backend.getDbUrl(projectId, environmentId), - }); - -/** - * Used only for storing query key - */ -export const projectBackendProjectEnvDatabasePreviewQueryOptions = ({ - projectId, - environmentId, -}: { - projectId: string; - environmentId: string; -}) => - queryOptions({ - gcTime: Number.POSITIVE_INFINITY, - staleTime: Number.POSITIVE_INFINITY, - enabled: false, - queryKey: [ - "project", - projectId, - "backend-env", - environmentId, - "database", - "preview", - ], - }); diff --git a/frontend/apps/hub/src/domains/project/queries/backend/types.ts b/frontend/apps/hub/src/domains/project/queries/backend/types.ts deleted file mode 100644 index 208753dbd2..0000000000 --- a/frontend/apps/hub/src/domains/project/queries/backend/types.ts +++ /dev/null @@ -1,134 +0,0 @@ -import * as Sentry from "@sentry/react"; -import { z } from "zod"; - -function getModuleCallOrNull(event: Event, url: string) { - if (event.request.method !== "POST") { - return null; - } - - const [ - modulesLiteral, - moduleName, - scriptsLiteral, - scriptName, - callLiteral, - ] = url.split("/").slice(1); - - if ( - modulesLiteral === "modules" && - scriptsLiteral === "scripts" && - callLiteral === "call" - ) { - return { - moduleName, - scriptName, - }; - } - - return null; -} - -const Event = z.object({ - request: z.object({ - headers: z.record(z.string()), - method: z.string(), - url: z.string(), - }), - response: z.object({ - status: z.number(), - }), -}); - -type Event = z.infer; - -export const BackendEvent = z - .object({ - dispatchEnvironment: z.string().optional(), - event: Event, - eventTimestamp: z.string(), - logs: z - .array( - z.object({ - level: z.string(), - message: z.array(z.string()), - timestamp: z.string(), - }), - ) - .optional(), - exceptions: z - .array( - z.object({ - stack: z.string().optional(), - message: z.string(), - timestamp: z.string(), - }), - ) - .optional(), - outcome: z - .literal("canceled") - .or(z.literal("exceededCpu")) - .or(z.string()), - scriptName: z.string(), - scriptVersion: z.object({ - id: z.string(), - }), - }) - .catch((ctx) => { - console.error(ctx.error); - Sentry.captureException(ctx.error); - return ctx.input; - }) - .transform((data) => { - const url = new URL(data.event.request.url); - - const backendCall = getModuleCallOrNull(data.event, url.pathname); - - return { - ...data, - backendCall, - eventDate: new Date(+data.eventTimestamp).toLocaleString(), - event: { - ...data.event, - request: { - ...data.event.request, - pathname: url.pathname, - fmtUrl: backendCall - ? `${backendCall.moduleName}.${backendCall.scriptName}` - : url.pathname, - }, - }, - logTimestamps: data.logs - ? [ - ...data.logs.map((log) => - new Date(+log.timestamp).toISOString(), - ), - ...(data.exceptions?.map((log) => - new Date(+log.timestamp).toISOString(), - ) ?? []), - ] - : [], - logs: data.logs - ? [ - ...data.logs.map((log) => ({ - type: log.level as "error" | "warn" | "log", - message: log.message.join("\n"), - })), - ...(data.exceptions?.map((log) => ({ - type: "error" as const, - message: [log.message, log.stack].join("\n"), - })) ?? []), - ] - : [], - }; - }); - -export type BackendEvent = z.infer; - -export const OuterbaseStarlinkResponse = z.object({ - response: z.object({ - url: z.string(), - }), -}); -export type OuterbaseStarlinkResponse = z.infer< - typeof OuterbaseStarlinkResponse ->; diff --git a/frontend/apps/hub/src/domains/project/queries/billing/mutations.ts b/frontend/apps/hub/src/domains/project/queries/billing/mutations.ts deleted file mode 100644 index 77ffb82fc5..0000000000 --- a/frontend/apps/hub/src/domains/project/queries/billing/mutations.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { queryClient, rivetEeClient } from "@/queries/global"; -import type { Rivet as RivetEe } from "@rivet-gg/api-ee"; -import { useMutation } from "@tanstack/react-query"; -import { projectBillingQueryOptions } from "../billing/query-options"; - -export const useUpdateProjectBillingMutation = ({ - onSuccess, -}: { - onSuccess?: () => void; -}) => { - return useMutation({ - mutationFn: ({ - projectId, - plan, - }: { - projectId: string; - } & RivetEe.ee.cloud.games.billing.UpdatePlanRequest) => - rivetEeClient.ee.cloud.games.billing.updatePlan(projectId, { - plan, - }), - onSuccess: async (data, values) => { - await queryClient.invalidateQueries( - projectBillingQueryOptions(values.projectId), - ); - onSuccess?.(); - }, - }); -}; diff --git a/frontend/apps/hub/src/domains/project/queries/billing/query-options.ts b/frontend/apps/hub/src/domains/project/queries/billing/query-options.ts deleted file mode 100644 index 125ac2ebc9..0000000000 --- a/frontend/apps/hub/src/domains/project/queries/billing/query-options.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { rivetEeClient } from "@/queries/global"; -import type { Rivet as RivetEe } from "@rivet-gg/api-ee"; -import { queryOptions } from "@tanstack/react-query"; - -export const groupBillingUsageQueryOptions = ({ - groupId, - startTs, - endTs, -}: { - groupId: string; - startTs: Date; - endTs: Date; -}) => - queryOptions({ - queryKey: [ - "group", - groupId, - "billing", - "usage", - { startTs, endTs }, - ] as const, - queryFn: ({ queryKey: [_, groupId], signal }) => - rivetEeClient.ee.cloud.groups.billing.getUsage( - groupId, - { - queryStartTs: startTs, - queryEndTs: endTs, - }, - { abortSignal: signal }, - ), - }); - -export const projectBillingUsageQueryOptions = ({ - projectId, - groupId, - startTs, - endTs, -}: { - projectId: string; - groupId: string; - startTs: Date; - endTs: Date; -}) => - queryOptions({ - ...groupBillingUsageQueryOptions({ groupId, startTs, endTs }), - select: (data) => data.games.find((game) => game.gameId === projectId), - }); - -export const projectBillingQueryOptions = ( - projectId: string, - opts: { enabled?: boolean } = {}, -) => { - return queryOptions({ - queryKey: ["project", projectId, "billing"], - queryFn: ({ - queryKey: [ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _, - projectId, - ], - signal, - }) => - rivetEeClient.ee.cloud.games.billing.get( - projectId, - {}, - { - abortSignal: signal, - }, - ), - enabled: opts.enabled, - // HACK: Work around race condition with Stripe API - retry: 15, - retryDelay: 1000, - }); -}; - -export const portalBillingSessionQueryOptions = ( - groupId: string, - intent: RivetEe.ee.cloud.groups.billing.CreateStripePortalSessionRequest["intent"], -) => - queryOptions({ - queryKey: ["group", groupId, "billing", "portal", intent], - staleTime: 5 * 60 * 1000, // 5 minutes - gcTime: 5 * 60 * 1000, // 5 minutes - queryFn: ({ signal }) => - rivetEeClient.ee.cloud.groups.billing.createStripePortalSession( - groupId, - { intent }, - { abortSignal: signal }, - ), - }); diff --git a/frontend/apps/hub/src/domains/project/queries/environment/mutations.ts b/frontend/apps/hub/src/domains/project/queries/environment/mutations.ts deleted file mode 100644 index 30fb452c85..0000000000 --- a/frontend/apps/hub/src/domains/project/queries/environment/mutations.ts +++ /dev/null @@ -1,262 +0,0 @@ -import { queryClient, rivetClient } from "@/queries/global"; -import type { Rivet } from "@rivet-gg/api-full"; -import { toast } from "@rivet-gg/components"; -import { useMutation } from "@tanstack/react-query"; -import { projectQueryOptions } from "../query-options"; -import { - projectEnvironmentLobbyQueryOptions, - projectEnvironmentQueryOptions, -} from "./query-options"; - -export const useEnvironmentMatchmakerUpdateConfigMutation = () => { - return useMutation({ - mutationFn: ({ - projectId, - environmentId, - lobbyCountMax, - maxPlayers, - }: { - projectId: string; - environmentId: string; - } & Rivet.cloud.games.namespaces.UpdateGameNamespaceMatchmakerConfigRequest) => - rivetClient.cloud.games.namespaces.updateGameNamespaceMatchmakerConfig( - projectId, - environmentId, - { lobbyCountMax, maxPlayers }, - ), - onSuccess: async (data, values) => { - await queryClient.invalidateQueries( - projectQueryOptions(values.projectId), - ); - await queryClient.invalidateQueries( - projectEnvironmentQueryOptions({ - projectId: values.projectId, - environmentId: values.environmentId, - }), - ); - }, - }); -}; - -export const useEnvironmentMatchmakeDeleteLobbyMutation = () => { - return useMutation({ - mutationFn: ({ - projectId, - lobbyId, - }: { - projectId: string; - environmentId: string; - lobbyId: string; - }) => - rivetClient.cloud.games.matchmaker.deleteMatchmakerLobby( - projectId, - lobbyId, - ), - onSuccess: async (_, values) => { - await queryClient.invalidateQueries( - projectEnvironmentLobbyQueryOptions({ - projectId: values.projectId, - environmentId: values.environmentId, - lobbyId: values.lobbyId, - }), - ); - }, - }); -}; - -export const useEnvironmentRemoveDomainMutation = () => { - return useMutation({ - mutationFn: ({ - projectId, - environmentId, - domain, - }: { - projectId: string; - environmentId: string; - domain: string; - }) => - rivetClient.cloud.games.namespaces.removeNamespaceDomain( - projectId, - environmentId, - domain, - ), - onSuccess: async (data, values) => { - await queryClient.invalidateQueries( - projectQueryOptions(values.projectId), - ); - await queryClient.invalidateQueries( - projectEnvironmentQueryOptions({ - projectId: values.projectId, - environmentId: values.environmentId, - }), - ); - }, - }); -}; - -export const useUpdateProjectEnvironmentVersionMutation = ({ - onSuccess, -}: { - onSuccess?: () => void; -}) => { - return useMutation({ - mutationFn: ({ - projectId, - environmentId, - versionId, - }: { - projectId: string; - environmentId: string; - } & Rivet.cloud.games.namespaces.UpdateGameNamespaceVersionRequest) => - rivetClient.cloud.games.namespaces.updateGameNamespaceVersion( - projectId, - environmentId, - { versionId }, - ), - onSuccess: async (data, values) => { - await queryClient.invalidateQueries( - projectQueryOptions(values.projectId), - ); - onSuccess?.(); - }, - }); -}; - -export const useEnvironmentDomainPublicAuthMutation = ({ - onSuccess, -}: { - onSuccess?: () => void; -} = {}) => { - return useMutation({ - mutationFn: ({ - projectId, - environmentId, - enabled, - }: { - projectId: string; - environmentId: string; - enabled: boolean; - }) => - rivetClient.cloud.games.namespaces.toggleNamespaceDomainPublicAuth( - projectId, - environmentId, - { - enabled, - }, - ), - onError: () => { - toast.error("Failed to update domain-based authentication"); - }, - onSuccess: async (data, values) => { - await queryClient.invalidateQueries( - projectQueryOptions(values.projectId), - ); - await queryClient.invalidateQueries( - projectEnvironmentQueryOptions({ - projectId: values.projectId, - environmentId: values.environmentId, - }), - ); - onSuccess?.(); - }, - }); -}; - -export const useEnvironmentAuthTypeMutation = ({ - onSuccess, -}: { - onSuccess?: () => void; -} = {}) => { - return useMutation({ - mutationFn: ({ - projectId, - environmentId, - authType, - }: { - projectId: string; - environmentId: string; - authType: Rivet.cloud.CdnAuthType; - }) => - rivetClient.cloud.games.namespaces.setNamespaceCdnAuthType( - projectId, - environmentId, - { - authType, - }, - ), - onError: () => { - toast.error("Failed to update authentication type"); - }, - onSuccess: async (data, values) => { - await queryClient.invalidateQueries( - projectQueryOptions(values.projectId), - ); - await queryClient.invalidateQueries( - projectEnvironmentQueryOptions({ - projectId: values.projectId, - environmentId: values.environmentId, - }), - ); - onSuccess?.(); - }, - }); -}; - -export const useEnvironmentUpdateCdnAuthUserMutation = () => { - return useMutation({ - mutationFn: ({ - projectId, - environmentId, - user, - password, - }: { - projectId: string; - environmentId: string; - } & Rivet.cloud.games.namespaces.UpdateNamespaceCdnAuthUserRequest) => - rivetClient.cloud.games.namespaces.updateNamespaceCdnAuthUser( - projectId, - environmentId, - { - user, - password, - }, - ), - }); -}; - -export const useEnvironmentRemoveCdnAuthUserMutation = () => { - return useMutation({ - mutationFn: ({ - projectId, - environmentId, - user, - }: { - projectId: string; - environmentId: string; - user: string; - }) => - rivetClient.cloud.games.namespaces.removeNamespaceCdnAuthUser( - projectId, - environmentId, - user, - ), - }); -}; - -export const useEnvironmentAddDomainMutation = () => { - return useMutation({ - mutationFn: ({ - projectId, - environmentId, - domain, - }: { - projectId: string; - environmentId: string; - } & Rivet.cloud.games.namespaces.AddNamespaceDomainRequest) => - rivetClient.cloud.games.namespaces.addNamespaceDomain( - projectId, - environmentId, - { domain }, - ), - }); -}; diff --git a/frontend/apps/hub/src/domains/project/queries/environment/query-options.ts b/frontend/apps/hub/src/domains/project/queries/environment/query-options.ts deleted file mode 100644 index 5a765f6510..0000000000 --- a/frontend/apps/hub/src/domains/project/queries/environment/query-options.ts +++ /dev/null @@ -1,309 +0,0 @@ -import { rivetClient } from "@/queries/global"; -import type { Rivet } from "@rivet-gg/api-full"; -import { queryOptions } from "@tanstack/react-query"; -import stripAnsi from "strip-ansi"; -import { getLiveLobbyStatus, getLobbyStatus } from "../../data/lobby-status"; -import { projectQueryOptions } from "../query-options"; - -export const projectEnvironmentsQueryOptions = (projectId: string) => { - return queryOptions({ - ...projectQueryOptions(projectId), - select: (data) => - // biome-ignore lint/style/noNonNullAssertion: when we get here, we know the project exists - projectQueryOptions(projectId).select?.(data).namespaces!, - }); -}; - -export const projectEnvironmentQueryOptions = ({ - projectId, - environmentId, -}: { - projectId: string; - environmentId: string; -}) => { - return queryOptions({ - queryKey: ["project", projectId, "environment", environmentId], - queryFn: ({ - queryKey: [ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _, - projectId, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - __, - environmentId, - ], - signal, - }) => - rivetClient.cloud.games.namespaces.getGameNamespaceById( - projectId, - environmentId, - { abortSignal: signal }, - ), - }); -}; - -export const projectEnvironmentDisplayNameQueryOptions = ({ - projectId, - environmentId, -}: { - projectId: string; - environmentId: string; -}) => - queryOptions({ - ...projectQueryOptions(projectId), - select: (data) => - projectQueryOptions(projectId) - .select?.(data) - .namespaces.find( - (namespace) => namespace.namespaceId === environmentId, - )?.displayName, - }); - -export const projectEnvironmentVersionQueryOptions = ({ - projectId, - environmentId, -}: { - projectId: string; - environmentId: string; -}) => { - return queryOptions({ - ...projectQueryOptions(projectId), - select: (data) => - projectQueryOptions(projectId) - .select?.(data) - .namespaces.find( - (namespace) => namespace.namespaceId === environmentId, - )?.version, - }); -}; - -export const projectEnvironmentLobbyQueryOptions = ( - { - projectId, - environmentId, - lobbyId, - }: { - projectId: string; - environmentId: string; - lobbyId: string; - }, - opts?: { refetchInterval?: number; throwOnError?: boolean }, -) => { - return queryOptions({ - queryKey: [ - "project", - projectId, - "environment", - environmentId, - "lobby", - lobbyId, - ], - refetchInterval: opts?.refetchInterval, - throwOnError: opts?.throwOnError, - queryFn: ({ - queryKey: [ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _, - projectId, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - __, - environmentId, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - ___, - lobbyId, - ], - signal, - }) => - rivetClient.cloud.games.namespaces.logs.getNamespaceLobby( - projectId, - environmentId, - lobbyId, - { abortSignal: signal }, - ), - select: (data) => ({ - ...data, - lobby: { - ...data.lobby, - readableStatus: getLobbyStatus( - data.lobby.status, - data.lobby.startTs, - ), - stopTs: data.lobby.status.stopped?.stopTs, - }, - }), - }); -}; - -export const projectEnvironmentTokenPublicQueryOptions = ({ - projectId, - environmentId, -}: { - projectId: string; - environmentId: string; -}) => { - return queryOptions({ - staleTime: 0, - gcTime: 0, - queryKey: [ - "project", - projectId, - "environment", - environmentId, - "token", - "public", - ], - queryFn: ({ - queryKey: [ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _, - projectId, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - __, - environmentId, - ], - signal, - }) => - rivetClient.cloud.games.namespaces.createGameNamespaceTokenPublic( - projectId, - environmentId, - { abortSignal: signal }, - ), - select: (data) => data.token, - }); -}; - -export const projectEnvironmentLogsLobbiesQueryOptions = ({ - projectId, - environmentId, -}: { - projectId: string; - environmentId: string; -}) => { - return queryOptions({ - queryKey: [ - "project", - projectId, - "environment", - environmentId, - "lobbies", - ], - queryFn: ({ - queryKey: [ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _, - projectId, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - __, - environmentId, - ], - signal, - }) => - rivetClient.cloud.games.namespaces.logs.listNamespaceLobbies( - projectId, - environmentId, - {}, - { abortSignal: signal }, - ), - select: (data) => - data.lobbies.map((lobby) => ({ - ...lobby, - readableStatus: getLobbyStatus(lobby.status, lobby.startTs), - })), - }); -}; - -export const projectEnvironmentLogsLobbyLogsQueryOptions = ( - { - projectId, - lobbyId, - stream, - }: { - projectId: string; - lobbyId: string; - } & Rivet.cloud.games.GetLobbyLogsRequest, - opts?: { refetchInterval?: number }, -) => { - return queryOptions({ - // watch does not work on this query - refetchInterval: opts?.refetchInterval, - queryKey: ["project", projectId, "lobby", lobbyId, "logs", stream], - queryFn: async ({ - queryKey: [ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _, - projectId, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - __, - lobbyId, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - ___, - stream, - ], - signal, - }) => { - const response = - await rivetClient.cloud.games.matchmaker.getLobbyLogs( - projectId, - lobbyId, - { - stream: stream as Rivet.cloud.games.LogStream, - }, - { abortSignal: signal }, - ); - return { - ...response, - lines: response.lines.map((line) => - stripAnsi(window.atob(line)), - ), - }; - }, - }); -}; - -export const projectEnvironmentLobbiesLiveQueryOptions = ({ - projectId, - environmentId, -}: { - projectId: string; - environmentId: string; -}) => { - return queryOptions({ - queryKey: [ - "project", - projectId, - "environment", - environmentId, - "lobbies", - "live", - ], - refetchInterval: 1000, - queryFn: async ({ - queryKey: [ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _, - projectId, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - __, - environmentId, - ], - signal, - }) => - rivetClient.cloud.games.namespaces.analytics.getAnalyticsMatchmakerLive( - projectId, - environmentId, - { abortSignal: signal }, - ), - select: (data) => ({ - ...data, - lobbies: data.lobbies - .map((lobby) => ({ - ...lobby, - readableStatus: getLiveLobbyStatus(lobby), - })) - .sort((a, b) => { - // sort by created time - return +b.createTs - +a.createTs; - }), - }), - }); -}; diff --git a/frontend/apps/hub/src/domains/project/queries/index.ts b/frontend/apps/hub/src/domains/project/queries/index.ts deleted file mode 100644 index 6b2758cdf1..0000000000 --- a/frontend/apps/hub/src/domains/project/queries/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -export * from "./mutations"; -export * from "./types"; -export * from "./query-options"; -export * from "./environment/mutations"; -export * from "./environment/query-options"; -export * from "./backend/query-options"; -export * from "./backend/mutations"; -export * from "./backend/helpers"; -export * from "./billing/query-options"; -export * from "./billing/mutations"; -export * from "./servers/query-options"; -export * from "./servers/mutations"; -export * from "./actors/query-options"; -export * from "./actors/mutations"; diff --git a/frontend/apps/hub/src/domains/project/queries/mutations.ts b/frontend/apps/hub/src/domains/project/queries/mutations.ts deleted file mode 100644 index f680592e1f..0000000000 --- a/frontend/apps/hub/src/domains/project/queries/mutations.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { queryClient, rivetClient } from "@/queries/global"; -import type { Rivet } from "@rivet-gg/api-full"; -import { toast } from "@rivet-gg/components"; -import { useMutation } from "@tanstack/react-query"; -import { - projectQueryOptions, - projectsByGroupQueryOptions, -} from "./query-options"; - -export const useProjectCreateMutation = ({ - onSuccess, -}: { - onSuccess?: (data: Rivet.cloud.GameFull) => void; -} = {}) => { - return useMutation({ - mutationFn: async (data: Rivet.cloud.games.CreateGameRequest) => - rivetClient.cloud.games.createGame(data), - onSuccess: async (data) => { - await queryClient.invalidateQueries(projectsByGroupQueryOptions()); - const project = await queryClient.ensureQueryData( - projectQueryOptions(data.gameId), - ); - await onSuccess?.(project.game); - }, - }); -}; - -export const useEnvironmentCreateMutation = ({ - onSuccess, -}: { - onSuccess?: ( - data: Rivet.cloud.games.namespaces.CreateGameNamespaceResponse, - ) => void; -} = {}) => { - return useMutation({ - mutationFn: ({ - projectId, - ...data - }: Rivet.cloud.games.namespaces.CreateGameNamespaceRequest & { - projectId: string; - }) => - rivetClient.cloud.games.namespaces.createGameNamespace( - projectId, - data, - ), - onSuccess: async (data, values) => { - await Promise.all([ - queryClient.invalidateQueries( - projectQueryOptions(values.projectId), - ), - queryClient.invalidateQueries(projectsByGroupQueryOptions()), - ]); - onSuccess?.(data); - }, - }); -}; - -export const useExportLobbyLogsMutation = () => { - return useMutation({ - mutationFn: ({ - projectId, - lobbyId, - stream, - }: { - projectId: string; - lobbyId: string; - } & Rivet.cloud.games.ExportLobbyLogsRequest) => - rivetClient.cloud.games.matchmaker.exportLobbyLogs( - projectId, - lobbyId, - { - stream, - }, - ), - onSuccess: async (data) => { - window.open(data.url, "_blank"); - toast.success("Logs exported successfully"); - }, - }); -}; - -const useProjectLogoUploadCompleteMutation = () => { - return useMutation({ - mutationFn: ({ - projectId, - uploadId, - }: { projectId: string; uploadId: string }) => - rivetClient.cloud.games.gameLogoUploadComplete(projectId, uploadId), - onSuccess(_, variables) { - return Promise.all([ - queryClient.invalidateQueries( - projectQueryOptions(variables.projectId), - ), - queryClient.invalidateQueries(projectsByGroupQueryOptions()), - ]); - }, - }); -}; - -export const useProjectLogoUploadMutation = (projectId: string) => { - const { mutateAsync } = useProjectLogoUploadCompleteMutation(); - return useMutation({ - mutationFn: ({ file }: { file: File }) => - rivetClient.cloud.games.gameLogoUploadPrepare(projectId, { - mime: file.type, - contentLength: file.size, - path: file.name, - }), - onSuccess: async (response, data) => { - await fetch(response.presignedRequest.url, { - method: "PUT", - body: data.file, - mode: "cors", - headers: { - "Content-Type": data.file.type, - }, - }); - await mutateAsync({ - projectId, - uploadId: response.uploadId, - }); - }, - }); -}; diff --git a/frontend/apps/hub/src/domains/project/queries/query-options.tsx b/frontend/apps/hub/src/domains/project/queries/query-options.tsx deleted file mode 100644 index 409dee4aed..0000000000 --- a/frontend/apps/hub/src/domains/project/queries/query-options.tsx +++ /dev/null @@ -1,333 +0,0 @@ -import { isRivetError } from "@/lib/utils"; -import { rivetClient, rivetEeClient } from "@/queries/global"; -import { getMetaWatchIndex } from "@/queries/utils"; -import { RivetError } from "@rivet-gg/api-full"; -import { loadModuleCategories } from "@rivet-gg/components"; -import { queryOptions } from "@tanstack/react-query"; - -export const projectsQueryOptions = () => { - return queryOptions({ - queryKey: ["projects"], - queryFn: ({ meta, signal }) => - rivetClient.cloud.games.getGames( - { - watchIndex: getMetaWatchIndex(meta), - }, - { abortSignal: signal }, - ), - select: (data) => data.games, - }); -}; - -export const projectsByGroupQueryOptions = () => { - return queryOptions({ - ...projectsQueryOptions(), - select: (data) => { - return data.groups.map((group) => { - return { - ...group, - projects: data.games.filter( - (game) => game.developer.groupId === group.groupId, - ), - }; - }); - }, - }); -}; - -export const groupsCountQueryOptions = () => { - return queryOptions({ - ...projectsByGroupQueryOptions(), - select: (data) => data.groups.length, - }); -}; - -export const groupProjectsQueryOptions = (groupId: string) => { - return queryOptions({ - queryKey: ["team", groupId, "projects"], - retry(failureCount, error) { - if (isRivetError(error) && error.statusCode === 404) { - return false; - } - return failureCount < 3; - }, - queryFn: async ({ signal, meta }) => { - const data = await rivetClient.cloud.games.getGames( - { - watchIndex: getMetaWatchIndex(meta), - }, - { abortSignal: signal }, - ); - - const group = data.groups.find( - (group) => group.groupId === groupId, - ); - if (!group) { - throw new RivetError({ - statusCode: 404, - body: { - message: "Group not found", - }, - }); - } - - const projects = data.games.filter( - (game) => game.developer.groupId === group.groupId, - ); - return { - ...group, - projects, - }; - }, - }); -}; - -export const groupOnwerQueryOptions = (groupId: string) => { - return queryOptions({ - ...groupProjectsQueryOptions(groupId), - select: (data) => data.ownerIdentityId, - }); -}; - -export const projectsCountQueryOptions = (groupId: string) => { - return queryOptions({ - ...groupProjectsQueryOptions(groupId), - select: (data) => data.projects.length, - }); -}; - -export const projectByIdQueryOptions = (projectNameId: string) => { - return queryOptions({ - ...projectsByGroupQueryOptions(), - select: (data) => - // biome-ignore lint/style/noNonNullAssertion: when we get here, we know the project exists - data.games.find((game) => game.nameId === projectNameId)!, - }); -}; - -export const projectQueryOptions = (projectId: string) => { - return queryOptions({ - queryKey: ["project", projectId], - queryFn: ({ queryKey: [_, projectId], signal, meta }) => - rivetClient.cloud.games.getGameById( - projectId, - { - watchIndex: getMetaWatchIndex(meta), - }, - { abortSignal: signal }, - ), - select: (data) => ({ - ...data.game, - namespaces: data.game.namespaces.map((environment) => ({ - ...environment, - version: data.game.versions.find( - (version) => version.versionId === environment.versionId, - ), - })), - }), - }); -}; - -export const environmentByIdQueryOptions = ({ - projectId, - environmentNameId, -}: { - projectId: string; - environmentNameId: string; -}) => { - return queryOptions({ - ...projectQueryOptions(projectId), - select: (data) => - // biome-ignore lint/style/noNonNullAssertion: when we get here, we know the environment exists - projectQueryOptions(projectId) - .select?.(data) - .namespaces.find( - (namespace) => namespace.nameId === environmentNameId, - )!, - }); -}; - -export const projectVersionsQueryOptions = (projectId: string) => { - return queryOptions({ - ...projectQueryOptions(projectId), - select: (data) => - projectQueryOptions(projectId) - .select?.(data) - .versions.sort( - (a, b) => b.createTs.getTime() - a.createTs.getTime(), - ), - }); -}; - -export const projectRegionsQueryOptions = (projectId: string) => { - return queryOptions({ - ...projectQueryOptions(projectId), - select: (data) => - // biome-ignore lint/style/noNonNullAssertion: when we get here, we know the regions exist - projectQueryOptions(projectId).select?.(data).availableRegions!, - }); -}; - -export const projectRegionQueryOptions = ({ - projectId, - regionId, -}: { - projectId: string; - regionId: string; -}) => { - return queryOptions({ - ...projectRegionsQueryOptions(projectId), - select: (data) => - projectRegionsQueryOptions(projectId) - .select?.(data) - .find((region) => region.regionId === regionId), - }); -}; - -export const projectVersionQueryOptions = ({ - projectId, - versionId, -}: { - projectId: string; - versionId: string; -}) => - queryOptions({ - ...projectQueryOptions(projectId), - select: (data) => - // biome-ignore lint/style/noNonNullAssertion: when we get here, we know the version exists - projectQueryOptions(projectId) - .select?.(data) - .versions.find((version) => version.versionId === versionId)!, - }); - -export const projectTokenCloudQueryOptions = ({ - projectId, -}: { projectId: string }) => { - return queryOptions({ - staleTime: 0, - gcTime: 0, - queryKey: ["project", projectId, "token", "cloud"], - queryFn: ({ - queryKey: [ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _, - projectId, - ], - }) => rivetClient.cloud.games.tokens.createCloudToken(projectId), - select: (data) => data.token, - }); -}; - -export const projectEnvTokenServiceQueryOptions = ({ - projectId, - environmentId, -}: { - projectId: string; - environmentId: string; -}) => { - return queryOptions({ - staleTime: 0, - gcTime: 0, - queryKey: [ - "project", - projectId, - "environment", - environmentId, - "token", - "service", - ], - queryFn: ({ - queryKey: [ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _, - projectId, - __, - environmentId, - ], - }) => - rivetClient.games.environments.tokens.createServiceToken( - projectId, - environmentId, - ), - select: (data) => data.token, - }); -}; - -export const projectMetadataQueryOptions = ({ - projectId, - environmentId, -}: { - projectId: string; - environmentId: string; -}) => { - return queryOptions({ - // no need to refetch this often - // the metadata is not expected to change often - staleTime: 24 * 60 * 60 * 1000, - queryKey: [ - "project", - projectId, - "environment", - environmentId, - "metadata", - ], - queryFn: async ({ queryKey: [_, projectId, __, environmentId] }) => { - const { game } = - await rivetClient.cloud.games.getGameById(projectId); - const legacyLobbiesEnabled = game.versions.length > 1; - - const bootstrap = await rivetClient.cloud.bootstrap(); - try { - if (bootstrap.cluster === "enterprise") { - // should throw when there is no backend - await rivetEeClient.ee.backend.get( - projectId, - environmentId, - ); - - // sometimes even if there is a backend, there are no variables - // that means the user has not used the backend yet - // so its safe to disable the backend modules - const { variables } = - await rivetEeClient.ee.backend.getVariables( - projectId, - environmentId, - ); - const backendModulesEnabled = - Object.keys(variables).length > 0; - - return { - legacyLobbiesEnabled, - backendModulesEnabled, - }; - } - } catch {} - - return { - legacyLobbiesEnabled, - backendModulesEnabled: false, - }; - }, - }); -}; - -export const modulesCategoriesQueryOptions = () => { - return queryOptions({ - queryKey: ["modules", "categories"], - queryFn: () => loadModuleCategories(), - }); -}; - -const FEATURED_MODULES = ["lobbies", "friends", "analytics"]; - -export const featuredModulesQueryOptions = () => { - return queryOptions({ - ...modulesCategoriesQueryOptions(), - queryKey: ["modules", "featured"], - select: (data) => { - return data - .flatMap((category) => category.modules) - .filter((module) => FEATURED_MODULES.includes(module.id)); - }, - }); -}; diff --git a/frontend/apps/hub/src/domains/project/queries/servers/mutations.ts b/frontend/apps/hub/src/domains/project/queries/servers/mutations.ts deleted file mode 100644 index 22825de533..0000000000 --- a/frontend/apps/hub/src/domains/project/queries/servers/mutations.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { queryClient, rivetClient } from "@/queries/global"; -import type { Rivet } from "@rivet-gg/api-full"; -import { useMutation } from "@tanstack/react-query"; -import { - projectBuildQueryOptions, - projectBuildsQueryOptions, - projectServersQueryOptions, - serverQueryOptions, -} from "./query-options"; - -export function useDestroyServerMutation() { - return useMutation({ - mutationFn: (opts: { - projectId: string; - environmentId: string; - serverId: string; - }) => - rivetClient.servers.destroy( - opts.projectId, - opts.environmentId, - opts.serverId, - ), - onSuccess: async (_, { projectId, environmentId, serverId }) => { - await queryClient.invalidateQueries( - serverQueryOptions({ projectId, environmentId, serverId }), - ); - await queryClient.invalidateQueries({ - ...projectServersQueryOptions({ projectId, environmentId }), - refetchType: "all", - }); - }, - }); -} - -export function usePatchBuildTagsMutation() { - return useMutation({ - mutationFn: ({ - projectId, - environmentId, - buildId, - ...request - }: { - projectId: string; - environmentId: string; - buildId: string; - } & Rivet.servers.PatchBuildTagsRequest) => - rivetClient.servers.builds.patchTags( - projectId, - environmentId, - buildId, - request, - ), - }); -} - -export function useCreateDynamicServerMutation({ - onSuccess, -}: { onSuccess?: () => void } = {}) { - return useMutation({ - mutationFn: ({ - projectId, - environmentId, - ...request - }: { - projectId: string; - environmentId: string; - } & Rivet.servers.CreateServerRequest) => - rivetClient.servers.create(projectId, environmentId, request), - onSuccess: async (_, { projectId, environmentId }) => { - await queryClient.invalidateQueries( - projectServersQueryOptions({ projectId, environmentId }), - ); - onSuccess?.(); - }, - }); -} - -export function useUpdateBuildTagsMutation({ - onSuccess, -}: { onSuccess?: () => void } = {}) { - return useMutation({ - mutationFn: ({ - projectId, - environmentId, - buildId, - ...request - }: { - projectId: string; - environmentId: string; - buildId: string; - } & Rivet.servers.PatchBuildTagsRequest) => - rivetClient.servers.builds.patchTags( - projectId, - environmentId, - buildId, - request, - ), - onSuccess: async (_, { projectId, environmentId, buildId }) => { - await Promise.allSettled([ - queryClient.invalidateQueries( - projectBuildsQueryOptions({ projectId, environmentId }), - ), - queryClient.invalidateQueries( - projectBuildQueryOptions({ - buildId, - projectId, - environmentId, - }), - ), - ]); - onSuccess?.(); - }, - }); -} diff --git a/frontend/apps/hub/src/domains/project/queries/servers/query-options.ts b/frontend/apps/hub/src/domains/project/queries/servers/query-options.ts deleted file mode 100644 index bc1215716a..0000000000 --- a/frontend/apps/hub/src/domains/project/queries/servers/query-options.ts +++ /dev/null @@ -1,376 +0,0 @@ -import { mergeWatchStreams } from "@/lib/watch-utilities"; -import { rivetClient } from "@/queries/global"; -import { getMetaWatchIndex } from "@/queries/utils"; -import { Rivet } from "@rivet-gg/api-full"; -import { - type InfiniteData, - infiniteQueryOptions, - queryOptions, -} from "@tanstack/react-query"; -import stripAnsi from "strip-ansi"; - -export const projectServersQueryOptions = ({ - projectId, - environmentId, -}: { projectId: string; environmentId: string }) => { - return infiniteQueryOptions({ - queryKey: [ - "project", - projectId, - "environment", - environmentId, - "servers", - ], - refetchInterval: 5000, - initialPageParam: "", - queryFn: ({ - signal: abortSignal, - pageParam, - queryKey: [_, projectId, __, environmentId], - }) => - rivetClient.servers.list( - projectId, - environmentId, - { - includeDestroyed: true, - cursor: pageParam ? pageParam : undefined, - }, - { abortSignal }, - ), - select: (data) => data.pages.flatMap((page) => page.servers || []), - getNextPageParam: (lastPage) => { - if (!lastPage.servers) return null; - return lastPage.servers[lastPage.servers?.length - 1]?.id; - }, - meta: { - updateCache: ( - data: InfiniteData, - client, - ) => { - for (const page of data.pages) { - for (const server of page.servers) { - client.setQueryData( - [ - "project", - projectId, - "environment", - environmentId, - "server", - server.id, - ], - (oldData) => { - if (!oldData) return oldData; - return { - server, - }; - }, - ); - } - } - }, - }, - }); -}; - -export const serverQueryOptions = ({ - projectId, - environmentId, - serverId, -}: { - projectId: string; - environmentId: string; - serverId: string; -}) => { - return queryOptions({ - queryKey: [ - "project", - projectId, - "environment", - environmentId, - "server", - serverId, - ], - queryFn: ({ - signal: abortSignal, - queryKey: [_, projectId, __, environmentId, ___, serverId], - }) => - rivetClient.servers.get(projectId, environmentId, serverId, { - abortSignal, - }), - select: (data) => ({ - ...data.server, - createTs: data.server.createdAt - ? new Date(data.server.createdAt) - : new Date(), - startTs: data.server.startedAt - ? new Date(data.server.startedAt) - : undefined, - destroyTs: data.server.destroyedAt - ? new Date(data.server.destroyedAt) - : undefined, - runtime: { - ...data.server.runtime, - arguments: data.server.runtime.arguments?.filter( - (arg) => arg !== "", - ), - }, - }), - }); -}; - -export const serverLogsQueryOptions = ( - { - projectId, - environmentId, - serverId, - stream, - }: { - projectId: string; - environmentId: string; - serverId: string; - stream: Rivet.servers.LogStream; - }, - opts: { refetchInterval?: number } = {}, -) => { - return queryOptions({ - ...opts, - queryKey: [ - "project", - projectId, - "environment", - environmentId, - "server", - serverId, - "logs", - stream, - ], - queryFn: ({ - signal: abortSignal, - meta, - queryKey: [ - _, - projectId, - __, - environmentId, - ___, - serverId, - ____, - stream, - ], - }) => - rivetClient.servers.logs.get( - projectId, - environmentId, - serverId, - { - stream: stream as Rivet.servers.LogStream, - watchIndex: getMetaWatchIndex(meta), - }, - { abortSignal }, - ), - select: (data) => ({ - ...data, - lines: data.lines.map((line) => stripAnsi(window.atob(line))), - }), - meta: { - watch: mergeWatchStreams, - }, - }); -}; - -export const serverErrorsQueryOptions = ({ - projectId, - environmentId, - serverId, -}: { - projectId: string; - environmentId: string; - serverId: string; -}) => { - return queryOptions({ - ...serverLogsQueryOptions({ - projectId, - environmentId, - serverId, - stream: Rivet.servers.LogStream.StdErr, - }), - select: (data) => data.lines.length > 0, - }); -}; - -export const projectBuildsQueryOptions = ({ - environmentId, - projectId, - tags = {}, -}: { - projectId: string; - environmentId: string; - tags?: Record; -}) => { - return queryOptions({ - queryKey: [ - "project", - projectId, - "environment", - environmentId, - "builds", - tags, - ] as const, - refetchInterval: 5000, - queryFn: ({ - queryKey: [ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _, - projectId, - __, - environmentId, - ___, - tags, - ], - signal: abortSignal, - }) => - rivetClient.servers.builds.list( - projectId, - environmentId, - { tagsJson: JSON.stringify(tags) }, - { - abortSignal, - }, - ), - select: (data) => data.builds, - }); -}; - -export const projectCurrentBuildsQueryOptions = ({ - projectId, - environmentId, -}: { - projectId: string; - environmentId: string; -}) => { - return queryOptions({ - ...projectBuildsQueryOptions({ - projectId, - environmentId, - }), - select: (data) => data.builds.filter((build) => build.tags?.current), - }); -}; - -export const projectBuildQueryOptions = ({ - projectId, - environmentId, - buildId, -}: { - projectId: string; - environmentId: string; - buildId: string; -}) => { - return queryOptions({ - queryKey: [ - "project", - projectId, - "environment", - environmentId, - "build", - buildId, - ], - queryFn: ({ - signal: abortSignal, - queryKey: [_, projectId, __, environmentId, ___, buildId], - }) => - rivetClient.servers.builds.get( - projectId, - environmentId, - buildId, - {}, - { - abortSignal, - }, - ), - select: (data) => data.build, - }); -}; - -export const buildQueryOptions = ({ - projectId, - environmentId, - buildId, -}: { - projectId: string; - environmentId: string; - buildId: string; -}) => { - return queryOptions({ - queryKey: [ - "project", - projectId, - "environment", - environmentId, - "build", - buildId, - ], - queryFn: ({ - signal: abortSignal, - queryKey: [_, projectId, __, environmentId, ___, buildId], - }) => - rivetClient.servers.builds.get( - projectId, - environmentId, - buildId, - {}, - { - abortSignal, - }, - ), - - select: (data) => data.build, - }); -}; - -export const regionsQueryOptions = ({ - projectId, - environmentId, -}: { projectId: string; environmentId: string }) => { - return queryOptions({ - queryKey: [ - "project", - projectId, - "environment", - environmentId, - "regions", - ], - queryFn: ({ - signal: abortSignal, - queryKey: [_, projectId, __, environmentId], - }) => - rivetClient.regions.list( - { - project: projectId, - environment: environmentId, - }, - { - abortSignal, - }, - ), - select: (data) => data.regions, - }); -}; - -export const regionQueryOptions = ({ - projectId, - environmentId, - regionId, -}: { - projectId: string; - environmentId: string; - regionId: string; -}) => { - return queryOptions({ - ...regionsQueryOptions({ projectId, environmentId }), - select: (data) => - regionsQueryOptions({ projectId, environmentId }) - .select?.(data) - .find((region) => region.id === regionId), - }); -}; diff --git a/frontend/apps/hub/src/domains/project/queries/types.ts b/frontend/apps/hub/src/domains/project/queries/types.ts deleted file mode 100644 index 0f3def8350..0000000000 --- a/frontend/apps/hub/src/domains/project/queries/types.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { Rivet } from "@rivet-gg/api-full"; -import type { LobbyStatus } from "../data/lobby-status"; - -export type GroupProjects = Rivet.group.GroupSummary & { - projects: Rivet.game.GameSummary[]; -}; - -export type Project = Rivet.game.GameSummary & { - namespaces: Rivet.cloud.NamespaceSummary[]; -}; - -export type Environment = Rivet.cloud.NamespaceSummary & { - version: Rivet.cloud.version.Summary | undefined; -}; - -export type LobbySummary = Rivet.cloud.LogsLobbySummary & { - readableStatus: LobbyStatus; -}; - -export type LiveLobbyLogs = Rivet.cloud.LobbySummaryAnalytics & { - readableStatus: LobbyStatus; -}; -export * from "./backend/types"; diff --git a/frontend/apps/hub/src/domains/project/views/billing-view.tsx b/frontend/apps/hub/src/domains/project/views/billing-view.tsx deleted file mode 100644 index d5cc6e959b..0000000000 --- a/frontend/apps/hub/src/domains/project/views/billing-view.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { groupBillingQueryOptions } from "@/domains/group/queries"; -import { projectQueryOptions } from "@/domains/project/queries"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { Billing } from "../components/billing/billing"; -import { MissingPaymentMethod } from "../components/billing/billing-missing-payment-method"; - -interface BillingViewProps { - projectId: string; -} - -export function BillingView({ projectId }: BillingViewProps) { - const { - data: { developerGroupId }, - } = useSuspenseQuery(projectQueryOptions(projectId)); - - const { data: groupBilling } = useSuspenseQuery( - groupBillingQueryOptions(developerGroupId), - ); - - if (!groupBilling.group.paymentMethodAttachedTs) { - return ( - - ); - } - - return ; -} diff --git a/frontend/apps/hub/src/domains/project/views/environment-overview.tsx b/frontend/apps/hub/src/domains/project/views/environment-overview.tsx deleted file mode 100644 index 559242963f..0000000000 --- a/frontend/apps/hub/src/domains/project/views/environment-overview.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { - ActionCard, - Badge, - Grid, - Text, - WithTooltip, -} from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { BackendDeploymentLink } from "../components/backend/backend-deployment-link"; -import { projectBackendQueryOptions } from "../queries"; - -interface OverviewCardProps { - environmentId: string; - projectId: string; -} - -function OverviewCard({ environmentId, projectId }: OverviewCardProps) { - const { data } = useSuspenseQuery( - projectBackendQueryOptions({ projectId, environmentId }), - ); - - return ( - - Created {data.createdAt.toLocaleString()} - - URL: - - -
- Tier{" "} - {data.tier}} - /> -
-
-
- ); -} - -interface ProjectBackendEnvironmentOverviewProps { - environmentId: string; - projectId: string; -} - -export function ProjectBackendEnvironmentOverview({ - environmentId, - projectId, -}: ProjectBackendEnvironmentOverviewProps) { - return ( - - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/views/environment-variables.tsx b/frontend/apps/hub/src/domains/project/views/environment-variables.tsx deleted file mode 100644 index 2c572e9f4b..0000000000 --- a/frontend/apps/hub/src/domains/project/views/environment-variables.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import * as ProjectBackendEnvironmentVariablesForm from "@/domains/project/forms/backend-env-variables-form"; -import { - Card, - CardContent, - CardFooter, - CardHeader, - CardTitle, -} from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { computeBackendEnvVariablesDiff } from "../helpers/backend-env-compute-diff-variables"; -import { - projectBackendEnvVariablesQueryOptions, - useBackendUpdateVariablesMutation, -} from "../queries"; - -interface ProjectBackendEnvironmentVariablesProps { - projectId: string; - environmentId: string; -} - -export function ProjectBackendEnvironmentVariables({ - environmentId, - projectId, -}: ProjectBackendEnvironmentVariablesProps) { - const { data } = useSuspenseQuery( - projectBackendEnvVariablesQueryOptions({ projectId, environmentId }), - ); - const { mutateAsync } = useBackendUpdateVariablesMutation(); - return ( - { - const diff = computeBackendEnvVariablesDiff( - data, - values.variables, - ); - if (diff.errors.length > 0) { - for (const { idx, error } of diff.errors) { - form.setError(`variables.${idx}.value`, { - type: "manual", - message: error, - }); - } - return; - } - return mutateAsync({ - projectId, - environmentId, - variables: diff.variables, - }); - }} - defaultValues={{ - variables: Object.entries(data).map(([key, value]) => ({ - key, - value: value.text, - isSecret: value.secret !== undefined, - })), - }} - > - - - Environment Variables - - - - - - - Save - - - - - ); -} diff --git a/frontend/apps/hub/src/domains/project/views/environment-versions.tsx b/frontend/apps/hub/src/domains/project/views/environment-versions.tsx deleted file mode 100644 index 77bd38ba98..0000000000 --- a/frontend/apps/hub/src/domains/project/views/environment-versions.tsx +++ /dev/null @@ -1,165 +0,0 @@ -import { useDialog } from "@/hooks/use-dialog"; -import type { Rivet } from "@rivet-gg/api-full"; -import { - Badge, - Button, - Card, - CardContent, - CardHeader, - CardTitle, - Flex, - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, - Text, -} from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { Link } from "@tanstack/react-router"; -import { Fragment } from "react/jsx-runtime"; -import { - projectEnvironmentsQueryOptions, - projectVersionsQueryOptions, -} from "../queries"; - -interface EnvironmentVersionRowProps extends Rivet.cloud.version.Summary { - isCurrent: boolean; - deployedEnvironments: Rivet.cloud.NamespaceSummary[]; - projectId: string; - projectNameId: string; - environmentId: string; -} - -function EnvironmentVersionRow({ - isCurrent, - displayName, - versionId, - projectId, - projectNameId, - environmentId, - createTs, - deployedEnvironments, -}: EnvironmentVersionRowProps) { - const { dialog, open } = useDialog.DeployEnvironmentVersion({ - projectId, - versionId, - environmentId, - }); - return ( - <> - {dialog} - - - {displayName} - - - {createTs.toLocaleString()} - - - {deployedEnvironments.map((environment, index, array) => ( - - - {environment.displayName} - - {index !== array.length - 1 ? ( - - {", "} - - ) : null} - - ))} - - - {isCurrent ? ( - - ) : ( - - )} - - - - ); -} - -interface EnvironmentVersionsProps { - projectId: string; - projectNameId: string; - environmentId: string; -} - -export function EnvironmentVersions({ - projectId, - projectNameId, - environmentId, -}: EnvironmentVersionsProps) { - const { data: versions } = useSuspenseQuery( - projectVersionsQueryOptions(projectId), - ); - const { data: namespaces } = useSuspenseQuery( - projectEnvironmentsQueryOptions(projectId), - ); - const currentEnvironment = namespaces.find( - (environment) => environment.namespaceId === environmentId, - ); - - return ( - - - - Versions - - - - - - - Name - Created at - Deployed to - - - - - {!versions || versions.length === 0 ? ( - - - There's no versions yet. - - - ) : null} - {versions?.map((version) => { - const isCurrentVersion = - version.versionId === - currentEnvironment?.versionId; - const deployedEnvironments = namespaces.filter( - (environment) => - environment.versionId === version.versionId, - ); - return ( - - ); - })} - -
-
-
- ); -} diff --git a/frontend/apps/hub/src/domains/project/views/project-environments.tsx b/frontend/apps/hub/src/domains/project/views/project-environments.tsx deleted file mode 100644 index e44becf2dd..0000000000 --- a/frontend/apps/hub/src/domains/project/views/project-environments.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import { projectEnvironmentsQueryOptions } from "@/domains/project/queries"; -import { - Button, - Card, - CardContent, - CardHeader, - CardTitle, - Code, - Flex, - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, - Text, -} from "@rivet-gg/components"; -import { Icon, faPlus } from "@rivet-gg/icons"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { Link, useNavigate } from "@tanstack/react-router"; -import { ProjectEnvironmentsTableActions } from "../components/project-environments-table-actions"; - -interface ProjectEnvironmentsViewProps { - projectId: string; - projectNameId: string; -} - -export function ProjectEnvironmentsView({ - projectId, - projectNameId, -}: ProjectEnvironmentsViewProps) { - const { data } = useSuspenseQuery( - projectEnvironmentsQueryOptions(projectId), - ); - - const navigate = useNavigate(); - - return ( - - - - Environments - - - - - - - - Name - Slug - - - - - {data.map((environment) => ( - { - navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId", - params: { - projectNameId, - environmentNameId: - environment.nameId, - }, - }); - }} - > - - {environment.displayName} - - - {environment.nameId} - - - - - - ))} - -
-
-
- ); -} diff --git a/frontend/apps/hub/src/domains/user/components/account-deletion-card.tsx b/frontend/apps/hub/src/domains/user/components/account-deletion-card.tsx deleted file mode 100644 index 8206053f2a..0000000000 --- a/frontend/apps/hub/src/domains/user/components/account-deletion-card.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { useAuth } from "@/domains/auth/contexts/auth"; -import { useDialog } from "@/hooks/use-dialog"; -import { Icon, faTriangleExclamation } from "@rivet-gg/icons"; - -import { - Card, - CardContent, - CardHeader, - CardTitle, - Flex, - Strong, - Switch, - Text, -} from "@rivet-gg/components"; -import { useIdentityDeletionMutation } from "../queries"; - -export function AccountDeletionCard() { - const { profile } = useAuth(); - - const { open, dialog } = useDialog.ConfirmAccountDeletion({}); - - const { isPending, mutate } = useIdentityDeletionMutation(); - - return ( - <> - {dialog} - - - Danger zone - - - - { - if (enabled) { - open(); - } else { - mutate(false); - } - }} - /> -
- {profile?.identity.awaitingDeletion ? ( - - - - Account deletion is pending. - - - ) : null} - - Mark your account for deletion. After 30 days of - this switch being on, your Rivet account and all - associated project accounts will be{" "} - permanently deleted. - -
-
-
-
- - ); -} diff --git a/frontend/apps/hub/src/domains/user/components/dialogs/confirm-account-deletion-dialog.tsx b/frontend/apps/hub/src/domains/user/components/dialogs/confirm-account-deletion-dialog.tsx deleted file mode 100644 index 040abd4e60..0000000000 --- a/frontend/apps/hub/src/domains/user/components/dialogs/confirm-account-deletion-dialog.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import type { DialogContentProps } from "@/hooks/use-dialog"; -import { - Button, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, - Strong, - Text, -} from "@rivet-gg/components"; -import { useIdentityDeletionMutation } from "../../queries"; - -interface ConfirmAccountDeletionDialogContentProps extends DialogContentProps {} - -export default function ConfirmAccountDeletionDialogContent({ - onClose, -}: ConfirmAccountDeletionDialogContentProps) { - const { isPending, mutate } = useIdentityDeletionMutation({ - onSuccess: onClose, - }); - - return ( - <> - - Confirm Account Deletion - -
- - Are you sure you want to delete your account? - - - - After 30 days, your account will be permanently - deleted. - - -
-
-
- - - - - ); -} diff --git a/frontend/apps/hub/src/domains/user/components/user-avatar-settings-card.tsx b/frontend/apps/hub/src/domains/user/components/user-avatar-settings-card.tsx deleted file mode 100644 index 78df72d84d..0000000000 --- a/frontend/apps/hub/src/domains/user/components/user-avatar-settings-card.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { - Card, - CardContent, - CardFooter, - CardHeader, - CardTitle, - toast, -} from "@rivet-gg/components"; -import * as UserAvatarForm from "../forms/user-avatar-form"; -import { useAvatarUploadMutation } from "../queries"; - -export function UserAvatarSettingsCard() { - const { mutateAsync } = useAvatarUploadMutation(); - return ( - { - try { - await mutateAsync({ file: values.image }); - form.reset(); - toast.success("Avatar updated"); - } catch { - form.setError("image", { - type: "manual", - message: "An error occurred while uploading the image", - }); - } - }} - defaultValues={{ image: undefined }} - > - - - Avatar - - - - - - Save - - - - ); -} diff --git a/frontend/apps/hub/src/domains/user/components/user-avatar.tsx b/frontend/apps/hub/src/domains/user/components/user-avatar.tsx deleted file mode 100644 index 16a759703b..0000000000 --- a/frontend/apps/hub/src/domains/user/components/user-avatar.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import type { Rivet } from "@rivet-gg/api-full"; -import { Avatar, AvatarFallback, AvatarImage } from "@rivet-gg/components"; - -interface UserAvatarProps - extends Pick {} - -export function UserAvatar({ avatarUrl, displayName }: UserAvatarProps) { - return ( - - - {displayName[0]} - - ); -} diff --git a/frontend/apps/hub/src/domains/user/components/user-name-settings-card.tsx b/frontend/apps/hub/src/domains/user/components/user-name-settings-card.tsx deleted file mode 100644 index a1c4417744..0000000000 --- a/frontend/apps/hub/src/domains/user/components/user-name-settings-card.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { useAuth } from "@/domains/auth/contexts/auth"; -import * as UserNameForm from "@/domains/group/forms/group-name-form"; -import { - Card, - CardContent, - CardFooter, - CardHeader, - CardTitle, - toast, -} from "@rivet-gg/components"; -import { useIdentityUpdateProfileMutation } from "../queries"; - -export function UserNameSettingsCard() { - const { profile } = useAuth(); - const { mutateAsync } = useIdentityUpdateProfileMutation(); - return ( - { - await mutateAsync({ displayName: values.name }); - form.reset(values); - toast.success("Profile updated"); - }} - defaultValues={{ name: profile?.identity.displayName }} - > - - - Profile - - - - - - Save - - - - ); -} diff --git a/frontend/apps/hub/src/domains/user/forms/user-avatar-form.tsx b/frontend/apps/hub/src/domains/user/forms/user-avatar-form.tsx deleted file mode 100644 index 2484c1cd93..0000000000 --- a/frontend/apps/hub/src/domains/user/forms/user-avatar-form.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { - FileInput, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, - createSchemaForm, - fileSize, -} from "@rivet-gg/components"; -import { type UseFormReturn, useFormContext } from "react-hook-form"; -import z from "zod"; - -const allowedTypes = ["image/png", "image/jpeg"]; - -export const formSchema = z.object({ - image: z - .custom() - .refine( - (file) => file.size <= fileSize.megabytes(2), - "File size should be less than 2MB.", - ) - .refine( - (file) => allowedTypes.includes(file.type), - `File type should be one of ${allowedTypes.join(", ")}`, - ), -}); - -export type FormValues = z.infer; -export type SubmitHandler = ( - values: FormValues, - form: UseFormReturn, -) => Promise; - -const { Form, Submit } = createSchemaForm(formSchema); -export { Form, Submit }; - -export const Image = () => { - const { control } = useFormContext(); - return ( - ( - - Avatar - - - name="image" - field={field} - accept={allowedTypes.join(", ")} - /> - - - - )} - /> - ); -}; diff --git a/frontend/apps/hub/src/domains/user/forms/user-name-form.tsx b/frontend/apps/hub/src/domains/user/forms/user-name-form.tsx deleted file mode 100644 index b09356ffb9..0000000000 --- a/frontend/apps/hub/src/domains/user/forms/user-name-form.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, - Input, - createSchemaForm, -} from "@rivet-gg/components"; -import { type UseFormReturn, useFormContext } from "react-hook-form"; -import z from "zod"; - -export const formSchema = z.object({ - name: z.string().max(25), -}); - -export type FormValues = z.infer; -export type SubmitHandler = ( - values: FormValues, - form: UseFormReturn, -) => Promise; - -const { Form, Submit } = createSchemaForm(formSchema); -export { Form, Submit }; - -export const Name = () => { - const { control } = useFormContext(); - return ( - ( - - Name - - - - - - )} - /> - ); -}; diff --git a/frontend/apps/hub/src/domains/user/layouts/profile-layout.tsx b/frontend/apps/hub/src/domains/user/layouts/profile-layout.tsx deleted file mode 100644 index 56e9190c8b..0000000000 --- a/frontend/apps/hub/src/domains/user/layouts/profile-layout.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import { useAuth } from "@/domains/auth/contexts/auth"; -import { - Flex, - Link, - Separator, - SidebarNavigation, - SidebarPageContent, -} from "@rivet-gg/components"; -import { Icon, faRightFromBracket } from "@rivet-gg/icons"; -import { Link as InternalLink } from "@tanstack/react-router"; -import type { ReactNode } from "react"; - -export interface ProfilePageProps { - children: ReactNode; -} - -function ProfilePage({ children }: ProfilePageProps) { - const { logout } = useAuth(); - - return ( - - - Your Account - - {/* - Features - */} - - - Logout - - - - Privacy Policy - - - Terms of Service - - - Support - - - } - > - - {children} - - - ); -} - -export { ProfilePage as Root }; diff --git a/frontend/apps/hub/src/domains/user/queries/index.ts b/frontend/apps/hub/src/domains/user/queries/index.ts deleted file mode 100644 index 6f6d5a8a9e..0000000000 --- a/frontend/apps/hub/src/domains/user/queries/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./query-options"; -export * from "./mutations"; diff --git a/frontend/apps/hub/src/domains/user/queries/mutations.ts b/frontend/apps/hub/src/domains/user/queries/mutations.ts deleted file mode 100644 index 490eb43123..0000000000 --- a/frontend/apps/hub/src/domains/user/queries/mutations.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { ls } from "@/lib/ls"; -import { queryClient, rivetClient } from "@/queries/global"; -import type { Rivet } from "@rivet-gg/api-full"; -import { useMutation } from "@tanstack/react-query"; -import { selfProfileQueryOptions } from "./query-options"; - -const useAvatarUploadCompleteMutation = () => { - return useMutation({ - mutationFn: ({ uploadId }: { uploadId: string }) => - rivetClient.identity.completeAvatarUpload(uploadId), - onSuccess() { - return Promise.all([ - queryClient.invalidateQueries(selfProfileQueryOptions()), - ]); - }, - }); -}; - -export const useAvatarUploadMutation = () => { - const { mutateAsync } = useAvatarUploadCompleteMutation(); - return useMutation({ - mutationFn: ({ file }: { file: File }) => - rivetClient.identity.prepareAvatarUpload({ - mime: file.type, - contentLength: file.size, - path: file.name, - }), - onSuccess: async (response, data) => { - await fetch(response.presignedRequest.url, { - method: "PUT", - body: data.file, - mode: "cors", - headers: { - "Content-Type": data.file.type, - }, - }); - await mutateAsync({ - uploadId: response.uploadId, - }); - }, - }); -}; - -export const useIdentityUpdateProfileMutation = () => { - return useMutation({ - mutationFn: (data: Rivet.identity.UpdateProfileRequest) => - rivetClient.identity.updateProfile(data), - onSuccess: async () => { - return Promise.all([ - queryClient.invalidateQueries(selfProfileQueryOptions()), - ]); - }, - }); -}; - -export const useIdentityDeletionMutation = ({ - onSuccess, -}: { - onSuccess?: () => void; -} = {}) => { - return useMutation({ - mutationFn: (markDeletion: boolean) => - markDeletion - ? rivetClient.identity.markDeletion() - : rivetClient.identity.unmarkDeletion(), - onSuccess: async () => { - await Promise.all([ - queryClient.invalidateQueries(selfProfileQueryOptions()), - ]); - onSuccess?.(); - return; - }, - }); -}; - -export const useLogoutMutation = () => { - return useMutation({ - mutationFn: () => - rivetClient.auth.tokens.refreshIdentityToken({ logout: true }), - async onSuccess(data) { - await queryClient.clear(); - ls.remove("rivet-token"); - }, - }); -}; - -export const useIdentityTokenMutation = () => { - return useMutation({ mutationKey: ["identityToken"] }); -}; diff --git a/frontend/apps/hub/src/domains/user/queries/query-options.ts b/frontend/apps/hub/src/domains/user/queries/query-options.ts deleted file mode 100644 index 95bbc10043..0000000000 --- a/frontend/apps/hub/src/domains/user/queries/query-options.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { timing } from "@rivet-gg/components"; -import { queryOptions } from "@tanstack/react-query"; -import { rivetClient } from "../../../queries/global"; -import { getMetaWatchIndex } from "../../../queries/utils"; -import { Changelog } from "./type"; - -export const selfProfileQueryOptions = (opts: { enabled?: boolean } = {}) => { - return queryOptions({ - ...opts, - queryKey: ["selfProfile"], - queryFn: ({ meta, signal }) => { - return rivetClient.identity.getSelfProfile( - { - watchIndex: getMetaWatchIndex(meta), - }, - { abortSignal: signal }, - ); - }, - meta: { watch: true }, - }); -}; - -export const selfProfileIdentityIdQueryOptions = () => { - return queryOptions({ - ...selfProfileQueryOptions(), - select: (data) => data.identity.identityId, - }); -}; - -export const changelogQueryOptions = () => { - return queryOptions({ - queryKey: ["changelog", __APP_BUILD_ID__], - staleTime: timing.hours(1), - queryFn: async () => { - const response = await fetch("https://rivet.gg/changelog.json"); - if (!response.ok) { - throw new Error("Failed to fetch changelog"); - } - const result = Changelog.parse(await response.json()); - return result; - }, - }); -}; diff --git a/frontend/apps/hub/src/domains/user/queries/type.ts b/frontend/apps/hub/src/domains/user/queries/type.ts deleted file mode 100644 index a66fa2627c..0000000000 --- a/frontend/apps/hub/src/domains/user/queries/type.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { z } from "zod"; - -export const ChangelogItem = z.object({ - published: z.string(), - images: z.array(z.object({ url: z.string() })), - title: z.string(), - description: z.string(), - slug: z.string(), - authors: z.array( - z.object({ - name: z.string(), - role: z.string(), - avatar: z.object({ url: z.string() }), - socials: z.object({ - twitter: z.string().optional(), - github: z.string().optional(), - bluesky: z.string().optional(), - }), - }), - ), -}); -export const Changelog = z.array(ChangelogItem); - -export type Changelog = z.infer; -export type ChangelogItem = z.infer; diff --git a/frontend/apps/hub/src/hooks/use-dialog.tsx b/frontend/apps/hub/src/hooks/use-dialog.tsx deleted file mode 100644 index a1d7dc307b..0000000000 --- a/frontend/apps/hub/src/hooks/use-dialog.tsx +++ /dev/null @@ -1,295 +0,0 @@ -import { - Dialog, - DialogContent, - type DialogProps, - DialogTitle, - VisuallyHidden, - cn, -} from "@rivet-gg/components"; -import { - type ComponentProps, - type ComponentType, - Suspense, - lazy, - useCallback, - useMemo, - useState, -} from "react"; - -export interface DialogContentProps { - onClose?: () => void; -} - -interface DialogConfig { - autoFocus?: boolean; - size?: "md" | "lg"; -} - -export const createDialogHook = < - // biome-ignore lint/suspicious/noExplicitAny: we don't know the type of the component, so we use any - Component extends Promise<{ default: ComponentType }>, ->( - component: Component, - opts: DialogConfig = { size: "md" }, -) => { - const DialogImpl = ({ - dialogProps, - ...props - }: ComponentProps["default"]> & { - dialogProps?: DialogProps; - }) => { - // biome-ignore lint/correctness/useExhaustiveDependencies: component here is a static value, won't change over time - const Content = useMemo(() => lazy(() => component), []); - - return ( - - - { - if (opts.autoFocus === false) { - return e.preventDefault(); - } - }} - > - - Dynamic title - - dialogProps?.onOpenChange?.(false)} - /> - - - - ); - }; - - const useHook = (props: ComponentProps["default"]>) => { - const [isOpen, setIsOpen] = useState(() => false); - - const close = useCallback(() => { - setIsOpen(false); - }, []); - - const open = useCallback(() => { - setIsOpen(true); - }, []); - - const handleOpenChange = useCallback((open: boolean) => { - setIsOpen(open); - }, []); - - return { - open, - close, - dialog: ( - - ), - }; - }; - - useHook.Dialog = DialogImpl; - - return useHook; -}; - -export const createDataDialogHook = < - const DataPropKeys extends string[], - // biome-ignore lint/suspicious/noExplicitAny: we don't know the type of the component, so we use any - Component extends Promise<{ default: ComponentType }>, ->( - keys: DataPropKeys, - component: Component, - opts: DialogConfig = {}, -) => { - return ( - props: Omit< - ComponentProps["default"]>, - DataPropKeys[number] - >, - ) => { - const [isOpen, setIsOpen] = useState(false); - const [data, setData] = - useState< - Pick< - ComponentProps["default"]>, - DataPropKeys[number] - > - >(); - - const close = useCallback(() => { - setIsOpen(false); - }, []); - - const open = useCallback( - ( - data: Pick< - ComponentProps["default"]>, - DataPropKeys[number] - >, - ) => { - setIsOpen(true); - setData(data); - }, - [], - ); - - // biome-ignore lint/correctness/useExhaustiveDependencies: component here is a static value, won't change over time - const Content = useMemo(() => lazy(() => component), []); - - return { - open, - dialog: ( - - { - if (opts.autoFocus === false) { - return e.preventDefault(); - } - }} - > - - - - ), - }; - }; -}; - -export function useDialog() {} - -useDialog.GenerateEnvironmentPublicToken = createDialogHook( - import( - "@/domains/project/components/dialogs/environment-generate-public-token-dialog" - ), - { - autoFocus: false, - }, -); - -useDialog.GenerateProjectCloudToken = createDialogHook( - import( - "@/domains/project/components/dialogs/project-generate-cloud-token-dialog" - ), - { - autoFocus: false, - }, -); -useDialog.GenerateProjectEnvServiceToken = createDialogHook( - import( - "@/domains/project/components/dialogs/environment-generate-service-token-dialog" - ), - { - autoFocus: false, - }, -); - -useDialog.CreateGroupProject = createDialogHook( - import("@/domains/project/components/dialogs/group-create-project-dialog"), -); - -useDialog.CreateProject = createDialogHook( - import("@/domains/project/components/dialogs/create-project-dialog"), -); - -useDialog.ManageCdnAuthUsers = createDialogHook( - import("@/domains/project/components/dialogs/cdn-manage-auth-users-dialog"), -); - -useDialog.CreateEnvironment = createDialogHook( - import("@/domains/project/components/dialogs/create-environment-dialog"), -); - -useDialog.ManageCdnCustomDomains = createDialogHook( - import( - "@/domains/project/components/dialogs/cdn-manage-custom-domains-dialog" - ), -); - -useDialog.DeployEnvironmentVersion = createDialogHook( - import( - "@/domains/project/components/dialogs/deploy-environment-version-dialog" - ), -); - -useDialog.ConfirmBillingPlan = createDataDialogHook( - ["plan"], - import("@/domains/project/components/dialogs/confirm-billing-plan-dialog"), -); - -useDialog.CreateGroupInvite = createDialogHook( - import("@/domains/group/components/dialogs/create-group-invite-dialog"), -); - -useDialog.ConfirmTransferOwnership = createDataDialogHook( - ["identityId"], - import( - "@/domains/group/components/dialogs/confirm-transfer-ownership-dialog" - ), -); - -useDialog.ConfirmMemberKick = createDataDialogHook( - ["identityId"], - import("@/domains/group/components/dialogs/confirm-member-kick-dialog"), -); - -useDialog.ConfirmMemberBan = createDataDialogHook( - ["identityId"], - import("@/domains/group/components/dialogs/confirm-member-ban-dialog"), -); - -useDialog.CreateGroup = createDialogHook( - import("@/domains/group/components/dialogs/create-group-dialog"), -); - -useDialog.ConfirmAccountDeletion = createDialogHook( - import("@/domains/user/components/dialogs/confirm-account-deletion-dialog"), -); - -useDialog.Feedback = createDialogHook( - import("@rivet-gg/components/dialogs/feedback-dialog"), -); - -useDialog.Secret = createDialogHook( - import("@//components/dialogs/secret-dialog"), -); - -useDialog.ConfirmOuterbaseConnection = createDialogHook( - import( - "@/domains/project/components/dialogs/confirm-outerbase-connection-dialog" - ), -); - -useDialog.ConfirmLeaveGroup = createDialogHook( - import("@/domains/group/components/dialogs/confirm-leave-group-dialog"), -); - -useDialog.EditBuildTags = createDialogHook( - import("@/domains/project/components/dialogs/edit-build-tags-dialog"), -); - -useDialog.CreateActor = createDialogHook( - import("@rivet-gg/components/actors/dialogs/create-actor-dialog"), -); - -useDialog.GoToActor = createDialogHook( - import("@rivet-gg/components/actors/dialogs/go-to-actor-dialog"), -); - -useDialog.EditRoute = createDialogHook( - import("@/domains/project/components/dialogs/edit-route-dialog"), -); - -useDialog.CreateRoute = createDialogHook( - import("@/domains/project/components/dialogs/create-route-dialog"), -); diff --git a/frontend/apps/hub/src/hooks/use-feature-flag.ts b/frontend/apps/hub/src/hooks/use-feature-flag.ts deleted file mode 100644 index bee9a2f597..0000000000 --- a/frontend/apps/hub/src/hooks/use-feature-flag.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { useFeatureFlagEnabled } from "posthog-js/react"; - -export type FeatureFlag = - | "hub-opengb-backend" - | "hub-upgraded-alert" - | (string & {}); - -export const useFeatureFlag = (flag: FeatureFlag) => { - return useFeatureFlagEnabled(flag); -}; diff --git a/frontend/apps/hub/src/index.css b/frontend/apps/hub/src/index.css deleted file mode 100644 index 61131ed697..0000000000 --- a/frontend/apps/hub/src/index.css +++ /dev/null @@ -1,54 +0,0 @@ -@import "@rivet-gg/components/theme.css"; - -@tailwind base; -@tailwind components; -@tailwind utilities; - -@layer base { - * { - @apply border-border; - } - body { - @apply bg-background text-foreground min-h-screen; - } - #root { - @apply min-h-screen; - } -} - -@layer utilities { - .overflow-r-gradient { - mask-image: linear-gradient(-90deg, rgba(0, 0, 0, 0) 0%, #000 45px); - } - - .step { - counter-increment: step; - } - - .step:before { - @apply absolute inline-flex h-9 w-9 items-center justify-center rounded-full border-4 border-background bg-primary text-center -indent-px font-mono text-base font-medium; - @apply ml-[-50px] mt-[-4px]; - content: counter(step); - } -} - -:root { - /* biome-ignore lint/correctness/noUnknownFunction: tailwind functions */ - --shiki-color-text: theme("colors.white"); - /* biome-ignore lint/correctness/noUnknownFunction: tailwind functions */ - --shiki-token-constant: theme("colors.violet.300"); - /* biome-ignore lint/correctness/noUnknownFunction: tailwind functions */ - --shiki-token-string: theme("colors.violet.300"); - /* biome-ignore lint/correctness/noUnknownFunction: tailwind functions */ - --shiki-token-comment: theme("colors.zinc.500"); - /* biome-ignore lint/correctness/noUnknownFunction: tailwind functions */ - --shiki-token-keyword: theme("colors.sky.300"); - /* biome-ignore lint/correctness/noUnknownFunction: tailwind functions */ - --shiki-token-parameter: theme("colors.pink.300"); - /* biome-ignore lint/correctness/noUnknownFunction: tailwind functions */ - --shiki-token-function: theme("colors.violet.300"); - /* biome-ignore lint/correctness/noUnknownFunction: tailwind functions */ - --shiki-token-string-expression: theme("colors.violet.300"); - /* biome-ignore lint/correctness/noUnknownFunction: tailwind functions */ - --shiki-token-punctuation: theme("colors.zinc.200"); -} diff --git a/frontend/apps/hub/src/layouts/page-centered.tsx b/frontend/apps/hub/src/layouts/page-centered.tsx deleted file mode 100644 index 9d8f65907d..0000000000 --- a/frontend/apps/hub/src/layouts/page-centered.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { Skeleton } from "@rivet-gg/components"; -import type { ReactNode } from "react"; - -interface PageCenteredProps { - children: ReactNode; -} - -const PageCentered = ({ children }: PageCenteredProps) => ( -
-
{children}
-
-); - -PageCentered.Skeleton = function PageCenteredSkeleton() { - return ( - - - - ); -}; - -export { PageCentered as Root }; diff --git a/frontend/apps/hub/src/layouts/root.tsx b/frontend/apps/hub/src/layouts/root.tsx deleted file mode 100644 index eeb6cfc6ab..0000000000 --- a/frontend/apps/hub/src/layouts/root.tsx +++ /dev/null @@ -1,154 +0,0 @@ -import { NavItem } from "@/components/header/nav-item"; -import { usePageLayout } from "@/lib/compute-page-layout"; -import { publicUrl } from "@/lib/utils"; -import { cn } from "@rivet-gg/components"; -import { - Icon, - faBluesky, - faDiscord, - faGithub, - faXTwitter, -} from "@rivet-gg/icons"; -import type { PropsWithChildren, ReactNode } from "react"; -import { Header as UiHeader } from "../components/header/header"; - -interface RootProps { - children: ReactNode; -} - -const Root = ({ children }: RootProps) => { - return
{children}
; -}; - -const Main = ({ children }: RootProps) => { - return ( -
- {children} -
- ); -}; - -const VisibleInFull = ({ children }: PropsWithChildren) => { - const layout = usePageLayout(); - return ( -
- {children} -
- ); -}; - -const Header = () => { - const layout = usePageLayout(); - return ( - - ); -}; - -const Footer = () => { - const layout = usePageLayout(); - - if (["actors", "v2"].includes(layout)) { - return null; - } - return ( -
-
-
-
-
- Rivet - © {new Date().getFullYear()} -
- - -
-
-
- - - - - - - - - - - - -
-
- - Home - - - Pricing - - - Docs - - - Enterprise - -
-
-
-
- ); -}; - -export { Root, Main, Header, Footer, VisibleInFull }; diff --git a/frontend/apps/hub/src/lib/async-validation.ts b/frontend/apps/hub/src/lib/async-validation.ts deleted file mode 100644 index 1b76c4132b..0000000000 --- a/frontend/apps/hub/src/lib/async-validation.ts +++ /dev/null @@ -1,87 +0,0 @@ -import type { Rivet } from "@rivet-gg/api-full"; -import { toast } from "@rivet-gg/components"; -import type { FieldValues, Path, UseFormReturn } from "react-hook-form"; -import z from "zod"; -import { - TraversableErrors, - VALIDATION_ERRORS, - type ValidationPaths, -} from "./traversable-errors"; -import { isRivetError } from "./utils"; - -export function validateAgainstApi({ - group, - errors, -}: { - group: TGroup; - errors: Rivet.ValidationError[]; -}) { - const traversable = new TraversableErrors(VALIDATION_ERRORS[group]); - traversable.load(errors.map((e) => e.path)); - - return { - setFormErrors: ( - form: UseFormReturn, - fields: Record, keyof ValidationPaths[TGroup]>, - ) => { - if (traversable.isEmpty()) - return { isValid: traversable.isEmpty() }; - - for (const [field, mappedField] of Object.entries(fields)) { - const fieldErrors = traversable.findFormatted( - mappedField as string, - ); - if (fieldErrors.length > 0) { - form.setError(field as Path, { - type: "manual", - message: fieldErrors[0] || "", - }); - } - } - - return { isValid: traversable.isEmpty() }; - }, - setSchemaIssues: ( - ctx: z.RefinementCtx, - fields: Record, keyof ValidationPaths[TGroup]>, - ) => { - if (traversable.isEmpty()) - return { isValid: traversable.isEmpty() }; - - for (const [field, mappedField] of Object.entries(fields)) { - const fieldErrors = traversable.findFormatted( - mappedField as string, - ); - if (fieldErrors.length > 0) { - ctx.addIssue({ - path: field.split("."), - code: z.ZodIssueCode.custom, - message: fieldErrors[0] || "", - }); - } - } - - return { isValid: traversable.isEmpty() }; - }, - }; -} - -export async function safeAsyncValidation( - ctx: z.RefinementCtx, - fn: () => Promise, - opts: { message?: string } = {}, -) { - try { - await fn(); - } catch (e) { - const msg = opts.message || "An error occurred while validating."; - - toast.error(msg, { - description: isRivetError(e) ? e.body.message : undefined, - }); - ctx.addIssue({ - path: [""], - code: z.ZodIssueCode.custom, - }); - } -} diff --git a/frontend/apps/hub/src/lib/compute-page-layout.tsx b/frontend/apps/hub/src/lib/compute-page-layout.tsx deleted file mode 100644 index 33cecfef56..0000000000 --- a/frontend/apps/hub/src/lib/compute-page-layout.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { - type MakeRouteMatchUnion, - type StaticDataRouteOption, - useMatches, -} from "@tanstack/react-router"; - -export function usePageLayout(): StaticDataRouteOption["layout"] { - const matches = useMatches(); - return computePageLayout(matches); -} - -export function computePageLayout( - matches: MakeRouteMatchUnion[], -): StaticDataRouteOption["layout"] { - let layout: StaticDataRouteOption["layout"] = "compact"; - - for (const match of matches) { - if (match.staticData.layout) { - layout = match.staticData.layout; - } - } - - return layout; -} diff --git a/frontend/apps/hub/src/lib/data/validation-errors.json b/frontend/apps/hub/src/lib/data/validation-errors.json deleted file mode 100644 index c85f7293cd..0000000000 --- a/frontend/apps/hub/src/lib/data/validation-errors.json +++ /dev/null @@ -1,216 +0,0 @@ -{ - "GAME_VERSION": { - "display-name": { - "too-short": "Version name is too short", - "too-long": "Version name is too long", - "not-unique": "Version name is not unique", - "invalid": "Version name is invalid" - }, - "config": { - "cdn": { - "no-site-id": "No CDN bundle specified", - "routes-meta": { - "too-many": "Too many routes" - }, - "routes": { - "glob": { - "invalid": "Invalid glob", - "not-unique": "Glob is not unique" - }, - "priority": { - "too-low": "Priority value too low", - "too-high": "Priority value too high" - }, - "middlewares-meta": { - "too-many": "Too many middlewares" - }, - "middlewares": { - "not-unique": "Can only have one of this type of middleware", - "custom-headers": { - "headers-meta": { - "too-many": "Too many headers" - }, - "headers": { - "name": { - "invalid": "Invalid header name", - "too-long": "Header name too long" - }, - "value": { - "too-long": "Header value too long" - } - } - } - } - } - }, - "matchmaker": { - "captcha": { - "requests-before-reverify": { - "too-high": "Requests before reverification too high" - }, - "verification-ttl": { - "too-high": "Time before reverification too high" - } - }, - "project-modes-meta": { - "too-few": "Must have at least one project mode", - "too-many": "Too many project modes" - }, - "project-modes": { - "name-id-invalid": "Invalid name (only A-Z, 0-9, and - are allowed)", - "name-not-unique": "Project mode name is not unique", - "player-counts": { - "max-players": { - "too-low": "General player count cannot be below 0", - "too-high": "General player count cannot be above 32" - }, - "max-players-direct": { - "too-low": "Direct player count cannot be below 0", - "too-high": "Direct player count cannot be above 32" - } - }, - "no-regions": "No regions selected", - "regions": { - "invalid": "Invalid region", - "tier-name-id-invalid": "Invalid tier selection", - "idle-lobbies": { - "min-gt-max": "Minimum must be less than or equal to the maximum", - "min-too-high": "Cannot have more than 16 min idle lobbies", - "max-too-high": "Cannot have more than 32 max idle lobbies" - } - }, - "no-build": "No docker build specified", - "args-too-many": "Too many arguments", - "args": { - "invalid": "Argument value is invalid", - "not-unique": "Argument is not unique", - "too-long": "Argument value is too long" - }, - "ports-too-many": "Too many ports", - "ports": { - "label-not-unique": "Port label is not unique", - "label-invalid": "Port label is invalid", - "port-protocol-not-unique": "Port/protocol pair is not unique", - "range-min-gt-max": "Range minimum must be less than or equal to the maximum", - "port-out-of-range": "Host network port must be within 26000 and 31999", - "ranges-overlap": "Ranges overlap", - "needs-project-guard": "HTTP/HTTPS ports require proxy to be set to Project Guard", - "unsupported-target-port": "Host networks do not support a target port, use port range instead", - "unsupported-port-range": "Project Guard network does not support port range", - "duplicate-port-and-port-range": "Cannot declare both port and port range", - "missing-port-and-port-range": "Missing port and port range", - "needs-host-network": "Ports without Project Gaurd require network mode to be set to host" - }, - "env-vars-too-many": "Too many env vars", - "env-vars": { - "key": { - "invalid": "Env var name is invalid", - "too-long": "Env var name is too long", - "conflicts-with-default": "Key conflicts with default key", - "not-unique": "Env var key is not unique" - }, - "value": { - "invalid": "Env var value is invalid", - "too-long": "Env var value is too long" - } - }, - "no-runtime": "No runtime specified" - } - }, - "kv": {}, - "identity": { - "custom-display-names-meta": { - "too-few": "Must have at least one display name", - "too-many": "Too many custom display names" - }, - "custom-display-names": { - "display-name": { - "invalid": "Invalid display name", - "too-short": "Display name is too short", - "too-long": "Display name is too long", - "not-unique": "Display name is not unique" - } - } - } - } - }, - "GAME_NAMESPACE": { - "display-name": { - "invalid": "Invalid name", - "too-short": "Environment name is too short", - "too-long": "Environment name is too long" - }, - "name-id": { - "invalid": "Invalid name id", - "not-unique": "Environment id is already taken", - "too-short": "Environment id is too short", - "too-long": "Environment id is too long" - } - }, - "GAME_NAMESPACE_CONFIG": { - "lobby-count": { - "too-low": "Lobby count too low", - "too-high": "Lobby count too high" - }, - "max-players": { - "too-low": "Max player count too low" - } - }, - "GAME": { - "display-name": { - "invalid": "Invalid display name", - "too-short": "Project display name is too short", - "too-long": "Project display name is too long" - }, - "name-id": { - "invalid": "Invalid name ID", - "not-unique": "Project name ID is already taken", - "too-short": "Project name ID is too short", - "too-long": "Project name ID is too long" - } - }, - "GROUP": { - "display-name-invalid": "Invalid name", - "not-unique": "Group name is already taken", - "too-short": "Group name is too short", - "too-long": "Group name is too long" - }, - "IDENTITY_PROFILE": { - "display-name": { - "invalid": "Invalid display name", - "too-short": "Display name is too short", - "too-long": "Display name is too long" - }, - "account-number-invalid": "Invalid account number", - "bio": { - "invalid": "Invalid biography", - "too-long": "Biography is too long" - }, - "handle-not-unique": "User handle is not unique" - }, - "GROUP_PROFILE": { - "display-name": { - "invalid": "Invalid display name", - "too-short": "Display name is too short", - "too-long": "Display name is too long", - "not-unique": "User handle is not unique" - }, - "bio": { - "invalid": "Invalid biography", - "too-long": "Biography is too long" - } - }, - "DEV_TOKEN": { - "ports-too-many": "Too many ports", - "ports": { - "label-not-unique": "Port label is not unique", - "label-invalid": "Port label is invalid", - "port-protocol-not-unique": "Port/protocol pair is not unique", - "range-min-gt-max": "Range minimum must be less than or equal to the maximum", - "ranges-overlap": "Ranges overlap", - "unsupported-port-range": "HTTP & HTTPS & TCP+TLS does not support port range", - "duplicate-port-and-port-range": "Cannot declare both port and port range", - "missing-port-and-port-range": "Missing port and port range" - } - } -} diff --git a/frontend/apps/hub/src/lib/guards.tsx b/frontend/apps/hub/src/lib/guards.tsx deleted file mode 100644 index ae7db5afc0..0000000000 --- a/frontend/apps/hub/src/lib/guards.tsx +++ /dev/null @@ -1,190 +0,0 @@ -import type { AuthContext } from "@/domains/auth/contexts/auth"; -import { - bootstrapQueryOptions, - clusterQueryOptions, -} from "@/domains/auth/queries/bootstrap"; -import { - projectByIdQueryOptions, - projectEnvironmentQueryOptions, - projectQueryOptions, - projectsByGroupQueryOptions, -} from "@/domains/project/queries"; -import { - type QueryClient, - useSuspenseQueries, - useSuspenseQuery, -} from "@tanstack/react-query"; -import { - Navigate, - type ParsedLocation, - notFound, - redirect, -} from "@tanstack/react-router"; -import type { PropsWithChildren } from "react"; -import { ls } from "./ls"; -import { isUuid } from "./utils"; - -export function GuardEnterprise({ children }: PropsWithChildren) { - const { data: cluster } = useSuspenseQuery(clusterQueryOptions()); - - if (cluster === "enterprise") { - return children; - } - - return null; -} - -export async function guardEnterprise({ - queryClient, -}: { queryClient: QueryClient }) { - const bootstrap = await queryClient.fetchQuery(bootstrapQueryOptions()); - - if (bootstrap.cluster === "oss") { - throw notFound(); - } -} - -export function GuardNewbie({ children }: PropsWithChildren) { - const [ - { - data: { cluster }, - }, - { data: groups }, - ] = useSuspenseQueries({ - queries: [bootstrapQueryOptions(), projectsByGroupQueryOptions()], - }); - - if (cluster === "oss") { - return ( - - ); - } - - if (groups.length > 0) { - return ( - - ); - } - - return children; -} - -export async function guardOssNewbie({ - queryClient, - auth, -}: { queryClient: QueryClient; auth: AuthContext }) { - const { cluster } = await queryClient.fetchQuery(bootstrapQueryOptions()); - - const { games: projects, groups } = await queryClient.fetchQuery( - projectsByGroupQueryOptions(), - ); - - if (cluster === "oss" && projects.length === 1) { - const { - game: { namespaces }, - } = await queryClient.fetchQuery( - projectQueryOptions(projects[0].gameId), - ); - - // In case the project has no namespaces, or we failed to fetch the project, redirect to the project page - if (namespaces.length > 0) { - throw redirect({ - to: "/projects/$projectNameId/environments/$environmentNameId", - params: { - projectNameId: projects[0].nameId, - environmentNameId: namespaces[0].nameId, - }, - from: "/", - }); - } - throw redirect({ - to: "/projects/$projectNameId", - params: { - projectNameId: projects[0].nameId, - }, - from: "/", - }); - } - - const lastTeam = ls.recentTeam.get(auth); - - if (lastTeam) { - throw redirect({ - to: "/teams/$groupId", - params: { groupId: lastTeam }, - from: "/", - }); - } - - if (groups.length > 0) { - throw redirect({ - to: "/teams/$groupId", - params: { groupId: groups[0].groupId }, - from: "/", - }); - } -} - -export async function guardUuids({ - queryClient, - projectNameId, - environmentNameId, - location, -}: { - queryClient: QueryClient; - projectNameId: string; - environmentNameId: string | undefined; - location: ParsedLocation; -}) { - let pathname = location.pathname; - - if (isUuid(projectNameId)) { - const response = await queryClient.fetchQuery( - projectsByGroupQueryOptions(), - ); - const project = response?.games.find((p) => p.gameId === projectNameId); - if (project) { - pathname = pathname.replace(projectNameId, project.nameId); - } - } - - if (environmentNameId && isUuid(environmentNameId)) { - const { games: projects } = await queryClient.fetchQuery( - projectByIdQueryOptions(projectNameId), - ); - - const envProject = projects.find((p) => p.nameId === projectNameId); - - if (!envProject) { - // bail out if we can't find the project - return; - } - - const { namespace: environment } = await queryClient.fetchQuery( - projectEnvironmentQueryOptions({ - projectId: envProject.gameId, - environmentId: environmentNameId, - }), - ); - - if (!environment) { - // bail out if we can't find the environment - return; - } - - pathname = pathname.replace(environmentNameId, environment.nameId); - } - - if (pathname !== location.pathname) { - throw redirect({ - to: pathname, - replace: true, - }); - } -} diff --git a/frontend/apps/hub/src/lib/ls.ts b/frontend/apps/hub/src/lib/ls.ts deleted file mode 100644 index 5610160498..0000000000 --- a/frontend/apps/hub/src/lib/ls.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { AuthContext } from "@/domains/auth/contexts/auth"; -import { ls as commonLs } from "@rivet-gg/components"; - -export const ls = { - ...commonLs, - recentTeam: { - get: (auth: AuthContext) => { - return ls.get( - `rivet-lastteam-${auth.profile?.identity.identityId}`, - ); - }, - set: (auth: AuthContext, groupId: string) => { - ls.set( - `rivet-lastteam-${auth.profile?.identity.identityId}`, - groupId, - ); - }, - remove: (auth: AuthContext) => { - ls.remove(`rivet-lastteam-${auth.profile?.identity.identityId}`); - }, - }, -}; diff --git a/frontend/apps/hub/src/lib/route-masks/index.ts b/frontend/apps/hub/src/lib/route-masks/index.ts deleted file mode 100644 index 5f7b1703fe..0000000000 --- a/frontend/apps/hub/src/lib/route-masks/index.ts +++ /dev/null @@ -1 +0,0 @@ -export const routeMasks = []; diff --git a/frontend/apps/hub/src/lib/traversable-errors.ts b/frontend/apps/hub/src/lib/traversable-errors.ts deleted file mode 100644 index 27b84245a1..0000000000 --- a/frontend/apps/hub/src/lib/traversable-errors.ts +++ /dev/null @@ -1,204 +0,0 @@ -import errImport from "./data/validation-errors.json"; - -interface ValidationErrors { - GAME: TraversableObject; - GROUP: TraversableObject; - GAME_VERSION: TraversableObject; - GAME_NAMESPACE: TraversableObject; - // IDENTITY_PROFILE: TraversableObject; - GROUP_PROFILE: TraversableObject; - // DEV_TOKEN: TraversableObject; - GAME_NAMESPACE_CONFIG: TraversableObject; -} - -export interface ValidationPaths { - GAME: { - "display-name": true; - "name-id": true; - }; - // GROUP: string; - GAME_VERSION: { - "display-name": true; - }; - GAME_NAMESPACE: { - "display-name": true; - "name-id": true; - }; - // IDENTITY_PROFILE: string; - GROUP_PROFILE: { - "display-name": true; - bio: true; - }; - GAME_NAMESPACE_CONFIG: { - "lobby-count": true; - "max-players": true; - }; -} - -// Typed JSON -export const VALIDATION_ERRORS = errImport as ValidationErrors; - -export type TraversableObject = { [key: string]: TraversableObject | string }; - -export class TraversableError { - path: string[]; - formattingInstructions: TraversableObject; - - constructor(formattingInstructions: TraversableObject, path: string[]) { - this.formattingInstructions = formattingInstructions; - this.path = path; - } - - format( - formatInstructions: TraversableObject = this.formattingInstructions, - ) { - return formatError(this.path, formatInstructions); - } -} - -export class TraversableErrors { - private errors: TraversableError[] = []; - private formattingInstructions: TraversableObject; - private prefix: string[] = []; - - constructor(formattingInstructions: TraversableObject, paths?: string[][]) { - if (!formattingInstructions) - throw new Error("Invalid formatting instructions"); - - this.formattingInstructions = formattingInstructions; - this.load(paths ?? []); - } - - load(paths: string[][]) { - this.errors = paths.map( - (a) => new TraversableError(this.formattingInstructions, a), - ); - } - - isEmpty() { - return this.count() === 0; - } - - count(...pathQuery: (string | number)[]) { - // Finds all errors that start with pathQuery - let errors = 0; - const expandedQuery = [...this.prefix, ...pathQuery]; - - // Return all errors - if (expandedQuery.length === 0) { - return this.errors.length; - } - - for (const error of this.errors) { - if (error.path.length < expandedQuery.length) continue; - - for (let i = 0, l = expandedQuery.length; i < l; i++) { - if (error.path[i] === expandedQuery[i].toString()) { - if (i === l - 1) { - errors++; - break; - } - } else { - break; - } - } - } - - return errors; - } - - // Finds all errors that start with pathQuery - find(...pathQuery: (string | number)[]) { - const errors = []; - const expandedQuery = [...this.prefix, ...pathQuery]; - - // Return all errors - if (expandedQuery.length === 0) { - return Array.from(this.errors); - } - - for (const error of this.errors) { - if (error.path.length < expandedQuery.length) continue; - - for (let i = 0, l = expandedQuery.length; i < l; i++) { - if (error.path[i] === expandedQuery[i].toString()) { - if (i === l - 1) { - errors.push(error); - break; - } - } else { - break; - } - } - } - - return errors; - } - - findFormatted(...pathQuery: (string | number)[]) { - return this.find(...pathQuery).map((a) => a.format()); - } - - // Finds all errors that start with pathQuery (only at a depth of +1) - findShallow(...pathQuery: (string | number)[]) { - const errors = []; - const expandedQuery = [...this.prefix, ...pathQuery]; - - for (const error of this.errors) { - if (error.path.length !== expandedQuery.length + 1) continue; - - if (expandedQuery.length === 0) { - errors.push(error); - } else { - for (let i = 0, l = expandedQuery.length; i < l; i++) { - if ( - error.path[i] === expandedQuery[i].toString() && - i === l - 1 - ) { - errors.push(error); - break; - } - } - } - } - - return errors; - } - - findShallowFormatted(...pathQuery: (string | number)[]) { - return this.findShallow(...pathQuery).map((a) => a.format()); - } - - branch(...pathQuery: (string | number)[]) { - const branch = new TraversableErrors(this.formattingInstructions); - branch.errors = this.errors; - branch.prefix = [...this.prefix, ...pathQuery.map((a) => a.toString())]; - - return branch; - } -} - -function formatError(error: string[], traverseStart: TraversableObject) { - let traverse: TraversableObject | string = traverseStart; - - for (const topic of error) { - // Skip indexes - if (!Number.isNaN(Number.parseInt(topic))) continue; - // Skip labels - if (topic.startsWith("*") && topic.endsWith("*")) continue; - - if (typeof traverse === "string") return traverse; - - // Check if error path exists - if (Object.prototype.hasOwnProperty.call(traverse, topic)) { - traverse = traverse[topic]; - } - // Invalid error path - else { - console.warn("Unknown traversable error", error); - return `${error.join(".")}`; - } - } - - return typeof traverse === "string" ? traverse : null; -} diff --git a/frontend/apps/hub/src/lib/utils.ts b/frontend/apps/hub/src/lib/utils.ts deleted file mode 100644 index fcf232f022..0000000000 --- a/frontend/apps/hub/src/lib/utils.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { RivetError as RivetEeError } from "@rivet-gg/api-ee"; -import { RivetError } from "@rivet-gg/api-full"; -import { type ErrorComponentProps, useRouter } from "@tanstack/react-router"; -import { useEffect } from "react"; -import { z } from "zod"; - -export function convertStringToId(x: string): string { - return x.toLowerCase().replace(/[^a-z0-9]+/g, "-"); -} - -export function isRivetError( - error: unknown, -): error is RivetError & { body: { message: string; code?: string } } { - return ( - (error instanceof RivetError || error instanceof RivetEeError) && - typeof error.body === "object" && - error.body !== null && - Object.hasOwn(error.body, "message") - ); -} - -const rivetLikeObject = z.object({ - body: z.object({ - message: z.string(), - code: z.string().optional(), - }), - statusCode: z.number().optional(), -}); - -export function isLikeRivetError( - error: unknown, -): error is z.infer { - return rivetLikeObject.safeParse(error).success; -} - -export function hasMethod( - obj: unknown, - methodName: TName, -): obj is { [key: string]: unknown } & { [K in TName]: () => unknown } { - return z - .object({ - [methodName]: z.function(), - }) - .safeParse(obj).success; -} - -export function noop() {} - -export function findDuplicated( - data: Record[], - key: Key, -) { - const duplicatesIdx: number[] = []; - const set = new Set(); - for (const [idx, variable] of [...data].reverse().entries()) { - if (set.has(variable[key])) { - duplicatesIdx.push(data.length - 1 - idx); - } - set.add(variable[key]); - } - - return duplicatesIdx; -} - -export const publicUrl = (path: string) => { - const filename = path.startsWith("/") ? path.slice(1) : path; - const url = import.meta.env.BASE_URL.endsWith("/") - ? import.meta.env.BASE_URL - : `${import.meta.env.BASE_URL}/`; - - return `${url}${filename}`; -}; - -const uuidSchema = z.string().uuid(); - -export const isUuid = ( - uuid: string, -): uuid is `${string}-${string}-${string}-${string}-${string}` => { - return uuidSchema.safeParse(uuid).success; -}; - -export const findUuidInUrl = (text: string) => { - for (const part of text.split("/")) { - if (isUuid(part)) { - return part; - } - } -}; - -export function RestOnRouteChange(props: ErrorComponentProps) { - const router = useRouter(); - - // biome-ignore lint/correctness/useExhaustiveDependencies: it's a router subscription - useEffect(() => { - return router.subscribe("onResolved", () => { - props.reset(); - }); - }, [router]); -} diff --git a/frontend/apps/hub/src/lib/watch-utilities.ts b/frontend/apps/hub/src/lib/watch-utilities.ts deleted file mode 100644 index 19ffaa3343..0000000000 --- a/frontend/apps/hub/src/lib/watch-utilities.ts +++ /dev/null @@ -1,12 +0,0 @@ -import _ from "lodash"; - -export function mergeWatchStreams( - oldData: unknown, - newChunk: unknown, -): unknown { - return _.mergeWith({}, oldData, newChunk, (objValue, srcValue) => { - if (_.isArray(objValue)) { - return objValue.concat(srcValue); - } - }); -} diff --git a/frontend/apps/hub/src/main.tsx b/frontend/apps/hub/src/main.tsx deleted file mode 100644 index 7c8684fb30..0000000000 --- a/frontend/apps/hub/src/main.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { StrictMode } from "react"; -import ReactDOM from "react-dom/client"; -import { App, router } from "./app"; -import "./index.css"; -import { initThirdPartyProviders } from "@rivet-gg/components"; -import { rivetClient } from "./queries/global"; - -initThirdPartyProviders(router, import.meta.env.DEV); - -rivetClient.cloud - .bootstrap() - .then((response) => { - run({ cacheKey: [response.deployHash, __APP_BUILD_ID__].join("-") }); - }) - .catch(() => { - run(); - }); - -function run({ cacheKey }: { cacheKey?: string } = {}) { - // biome-ignore lint/style/noNonNullAssertion: it should always be present - const rootElement = document.getElementById("root")!; - if (!rootElement.innerHTML) { - const root = ReactDOM.createRoot(rootElement); - root.render( - - - , - ); - } -} diff --git a/frontend/apps/hub/src/queries/global.ts b/frontend/apps/hub/src/queries/global.ts deleted file mode 100644 index b6402fb5b3..0000000000 --- a/frontend/apps/hub/src/queries/global.ts +++ /dev/null @@ -1,178 +0,0 @@ -import { ls } from "@/lib/ls"; -import { isRivetError } from "@/lib/utils"; -import { RivetClient as RivetEeClient } from "@rivet-gg/api-ee"; -import { RivetClient } from "@rivet-gg/api-full"; -import { - type APIResponse, - type Fetcher, - fetcher, -} from "@rivet-gg/api-full/core"; -import { getConfig, timing, toast } from "@rivet-gg/components"; -import { broadcastQueryClient } from "@tanstack/query-broadcast-client-experimental"; -import { createSyncStoragePersister } from "@tanstack/query-sync-storage-persister"; -import { - type DefaultError, - MutationCache, - MutationObserver, - QueryCache, - QueryClient, - type UseMutationOptions, -} from "@tanstack/react-query"; -import superjson from "superjson"; -import { watchBlockingQueries } from "./watch"; - -declare module "@tanstack/react-query" { - interface Register { - queryMeta: { - /** - * Injected by the watch function to indicate the index to watch for - * do not use this directly - */ - __watcher?: { index: string }; - /** - * If true, the query will be watched for a response - */ - watch?: - | true - | ((oldData: unknown, streamChunk: unknown) => unknown); - - /** - * Runs when the query is updated - */ - updateCache?: ( - // biome-ignore lint/suspicious/noExplicitAny: we don't know the shape of the data, it's up to the user to define it - data: any, - queryClient: QueryClient, - ) => Promise | void; - }; - } -} - -const logout = async () => { - await queryClient.cancelQueries(); - queryClient.clear(); - ls.remove("rivet-token"); - window.location.reload(); -}; - -const queryCache = new QueryCache({ - onSuccess: async (data, query) => { - if (query.meta?.updateCache) { - await query.meta.updateCache(data, queryClient); - } - }, - onError: (error) => { - if (isRivetError(error)) { - if ( - error.body.code === "TOKEN_REVOKED" || - error.body.code === "TOKEN_INVALID" || - error.body.code === "CLAIMS_ENTITLEMENT_EXPIRED" - ) { - logout(); - } - } - }, -}); - -const mutationCache = new MutationCache({ - onError(error, variables, context, mutation) { - console.error(error); - if (mutation.meta?.hideErrorToast) { - return; - } - toast.error("Error occurred while performing the operation.", { - description: isRivetError(error) ? error.body.message : undefined, - }); - }, -}); - -export const queryClient = new QueryClient({ - defaultOptions: { - queries: { - staleTime: 5 * 1000, - gcTime: 1000 * 60 * 60 * 24, - retry: 2, - refetchOnWindowFocus: false, - refetchOnReconnect: false, - }, - }, - queryCache, - mutationCache, -}); - -export const queryClientPersister = createSyncStoragePersister({ - storage: window.localStorage, - serialize: superjson.stringify, - deserialize: superjson.parse, -}); - -queryClient.setMutationDefaults(["identityToken"], { - scope: { id: "identityToken" }, - gcTime: timing.minutes(15), - mutationFn: () => - rivetClientTokeneless.auth.tokens.refreshIdentityToken({ - logout: false, - }), - onSuccess: async (data) => { - ls.set("rivet-token", data); - }, -}); - -const tokenMutationObserver = new MutationObserver(queryClient, { - mutationKey: ["identityToken"], -}); - -const clientOptions: RivetClient.Options = { - environment: getConfig().apiUrl, - fetcher: async ( - args: Fetcher.Args, - ): Promise> => { - const headers = args.headers || {}; - - headers["X-Fern-Language"] = undefined; - headers["X-Fern-Runtime"] = undefined; - headers["X-Fern-Runtime-Version"] = undefined; - - const response = await fetcher({ - ...args, - withCredentials: true, - maxRetries: 0, - timeoutMs: 30_000, // 30 seconds - }); - - return response; - }, - token: async () => { - const result = ls.get("rivet-token"); - if (!result || new Date(result.exp).getTime() < Date.now()) { - await tokenMutationObserver.mutate(); - return ls.get("rivet-token").token; - } - return result.token; - }, -}; - -export const rivetClientTokeneless = new RivetClient({ - environment: clientOptions.environment, - fetcher: clientOptions.fetcher, -}); -export const rivetClient = new RivetClient(clientOptions); -export const rivetEeClient = new RivetEeClient(clientOptions); - -watchBlockingQueries(queryClient); - -broadcastQueryClient({ - queryClient, - broadcastChannel: "rivet-gg-hub", -}); - -export function mutationOptions< - TData = unknown, - TError = DefaultError, - TVariables = void, - TContext = unknown, ->( - options: UseMutationOptions, -): UseMutationOptions { - return options; -} diff --git a/frontend/apps/hub/src/queries/types.ts b/frontend/apps/hub/src/queries/types.ts deleted file mode 100644 index 6888a66e98..0000000000 --- a/frontend/apps/hub/src/queries/types.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { z } from "zod"; - -export const OuterbaseCommonResponse = z.object({ - success: z.boolean(), -}); - -export const OuterbaseError = OuterbaseCommonResponse.extend({ - success: z.literal(false), - error: z.object({ - code: z.string(), - title: z.string(), - description: z.string(), - }), -}); diff --git a/frontend/apps/hub/src/queries/utils.ts b/frontend/apps/hub/src/queries/utils.ts deleted file mode 100644 index 4a625eefd5..0000000000 --- a/frontend/apps/hub/src/queries/utils.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { Rivet } from "@rivet-gg/api-full"; -import type { QueryMeta } from "@tanstack/react-query"; - -export const getMetaWatchIndex = ( - meta: QueryMeta | undefined, -): Rivet.WatchQuery => { - return meta?.__watcher?.index; -}; diff --git a/frontend/apps/hub/src/queries/watch.ts b/frontend/apps/hub/src/queries/watch.ts deleted file mode 100644 index 491ea9a8a3..0000000000 --- a/frontend/apps/hub/src/queries/watch.ts +++ /dev/null @@ -1,93 +0,0 @@ -import type { Query, QueryClient } from "@tanstack/react-query"; -import { z } from "zod"; -import { queryClient } from "./global"; - -const watchResponseFragment = z.object({ - watch: z.object({ index: z.string() }), -}); - -async function watch(query: Query) { - try { - await query.promise; - } catch (error) { - // the query failed/cancelled, we should stop watching - return; - } - const watchQueryState = queryClient.getQueryState([ - ...query.queryKey, - "watch", - ]); - - if (watchQueryState?.fetchStatus === "fetching") { - // it means the watch query is already being fetched, so we don't need to watch it again - return; - } - - while (true) { - try { - await query.promise; - const watchOptsParseResult = watchResponseFragment.safeParse( - query.state.data, - ); - - if (!watchOptsParseResult.success) { - // last query didn't have watch options, we should stop watching - break; - } - - const watchOpts = watchOptsParseResult.data; - - const result = await queryClient.fetchQuery({ - ...query.options, - retry: 0, - gcTime: 0, - staleTime: 0, - queryKey: [...query.queryKey, "watch"], - queryHash: JSON.stringify([...query.queryKey, "watch"]), - meta: { __watcher: { index: watchOpts.watch.index } }, - }); - - if (!result) { - break; - } - - // update the query with the new data - queryClient.setQueryData( - query.queryKey, - typeof query.meta?.watch === "function" - ? query.meta.watch(query.state.data, result) - : result, - ); - } catch (error) { - // something went wrong, we should stop watching - // probably the query was cancelled - break; - } - } -} - -async function stopWatching(query: Query) { - if (query.getObserversCount() <= 0) { - const watchQuery = queryClient - .getQueryCache() - .find({ queryKey: [...query.queryKey, "watch"] }); - if (watchQuery) { - watchQuery.cancel({ silent: true }); - queryClient.getQueryCache().remove(watchQuery); - watchQuery.destroy(); - } - } -} - -export function watchBlockingQueries(queryClient: QueryClient) { - queryClient.getQueryCache().subscribe((event) => { - if (event.type === "observerAdded") { - if (event.query.meta?.watch) { - watch(event.query); - } - } - if (event.type === "observerRemoved") { - stopWatching(event.query); - } - }); -} diff --git a/frontend/apps/hub/src/routeTree.gen.ts b/frontend/apps/hub/src/routeTree.gen.ts deleted file mode 100644 index b415826f6b..0000000000 --- a/frontend/apps/hub/src/routeTree.gen.ts +++ /dev/null @@ -1,1651 +0,0 @@ -/* eslint-disable */ - -// @ts-nocheck - -// noinspection JSUnusedGlobalSymbols - -// This file was automatically generated by TanStack Router. -// You should NOT make any changes in this file as it will be overwritten. -// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. - -// Import Routes - -import { Route as rootRoute } from './routes/__root' -import { Route as AuthenticatedImport } from './routes/_authenticated' -import { Route as AuthenticatedBillingImport } from './routes/_authenticated/billing' -import { Route as AuthenticatedLayoutImport } from './routes/_authenticated/_layout' -import { Route as AuthenticatedLayoutIndexImport } from './routes/_authenticated/_layout/index' -import { Route as AuthenticatedInviteInviteCodeImport } from './routes/_authenticated/invite.$inviteCode' -import { Route as AuthenticatedDevicesLinkImport } from './routes/_authenticated/devices.link' -import { Route as AuthenticatedLayoutMyProfileImport } from './routes/_authenticated/_layout/my-profile' -import { Route as AuthenticatedLayoutMyProfileIndexImport } from './routes/_authenticated/_layout/my-profile/index' -import { Route as AuthenticatedDevicesLinkTokenImport } from './routes/_authenticated/devices.link_.$token' -import { Route as AuthenticatedLayoutTeamsGroupIdImport } from './routes/_authenticated/_layout/teams/$groupId' -import { Route as AuthenticatedLayoutProjectsProjectNameIdImport } from './routes/_authenticated/_layout/projects/$projectNameId' -import { Route as AuthenticatedLayoutMyProfileFeaturesImport } from './routes/_authenticated/_layout/my-profile/features' -import { Route as AuthenticatedLayoutGamesSplatImport } from './routes/_authenticated/_layout/games/$' -import { Route as AuthenticatedLayoutTeamsGroupIdIndexImport } from './routes/_authenticated/_layout/teams/$groupId/index' -import { Route as AuthenticatedLayoutProjectsProjectNameIdIndexImport } from './routes/_authenticated/_layout/projects/$projectNameId/index' -import { Route as AuthenticatedLayoutTeamsGroupIdSettingsImport } from './routes/_authenticated/_layout/teams/$groupId/settings' -import { Route as AuthenticatedLayoutTeamsGroupIdMembersImport } from './routes/_authenticated/_layout/teams/$groupId/members' -import { Route as AuthenticatedLayoutTeamsGroupIdBillingImport } from './routes/_authenticated/_layout/teams/$groupId/billing' -import { Route as AuthenticatedLayoutProjectsProjectNameIdTokensImport } from './routes/_authenticated/_layout/projects/$projectNameId/tokens' -import { Route as AuthenticatedLayoutProjectsProjectNameIdSettingsImport } from './routes/_authenticated/_layout/projects/$projectNameId/settings' -import { Route as AuthenticatedLayoutProjectsProjectNameIdBillingImport } from './routes/_authenticated/_layout/projects/$projectNameId/billing' -import { Route as AuthenticatedLayoutTeamsGroupIdSettingsIndexImport } from './routes/_authenticated/_layout/teams/$groupId/settings/index' -import { Route as AuthenticatedLayoutProjectsProjectNameIdSettingsIndexImport } from './routes/_authenticated/_layout/projects/$projectNameId/settings/index' -import { Route as AuthenticatedLayoutProjectsProjectNameIdNamespacesSplatImport } from './routes/_authenticated/_layout/projects/$projectNameId/namespaces/$' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdIndexImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/index' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdVersionsImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/versions' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdTokensImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/tokens' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdMatchmakerImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/matchmaker' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdCdnImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/cdn' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBuildsImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/builds' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2Import } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesIndexImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/index' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendIndexImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/index' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersSplatImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers/$' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesSettingsImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/settings' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesLogsImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/logs' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendVariablesImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/variables' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendLogsImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/logs' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2SettingsImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/settings' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2LogsImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/logs' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2FunctionsImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/functions' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ContainersImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/containers' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorsImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/actors' -import { Route as AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorVersionsImport } from './routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/actor-versions' - -// Create/Update Routes - -const AuthenticatedRoute = AuthenticatedImport.update({ - id: '/_authenticated', - getParentRoute: () => rootRoute, -} as any) - -const AuthenticatedBillingRoute = AuthenticatedBillingImport.update({ - id: '/billing', - path: '/billing', - getParentRoute: () => AuthenticatedRoute, -} as any) - -const AuthenticatedLayoutRoute = AuthenticatedLayoutImport.update({ - id: '/_layout', - getParentRoute: () => AuthenticatedRoute, -} as any) - -const AuthenticatedLayoutIndexRoute = AuthenticatedLayoutIndexImport.update({ - id: '/', - path: '/', - getParentRoute: () => AuthenticatedLayoutRoute, -} as any) - -const AuthenticatedInviteInviteCodeRoute = - AuthenticatedInviteInviteCodeImport.update({ - id: '/invite/$inviteCode', - path: '/invite/$inviteCode', - getParentRoute: () => AuthenticatedRoute, - } as any) - -const AuthenticatedDevicesLinkRoute = AuthenticatedDevicesLinkImport.update({ - id: '/devices/link', - path: '/devices/link', - getParentRoute: () => AuthenticatedRoute, -} as any) - -const AuthenticatedLayoutMyProfileRoute = - AuthenticatedLayoutMyProfileImport.update({ - id: '/my-profile', - path: '/my-profile', - getParentRoute: () => AuthenticatedLayoutRoute, - } as any) - -const AuthenticatedLayoutMyProfileIndexRoute = - AuthenticatedLayoutMyProfileIndexImport.update({ - id: '/', - path: '/', - getParentRoute: () => AuthenticatedLayoutMyProfileRoute, - } as any) - -const AuthenticatedDevicesLinkTokenRoute = - AuthenticatedDevicesLinkTokenImport.update({ - id: '/devices/link_/$token', - path: '/devices/link/$token', - getParentRoute: () => AuthenticatedRoute, - } as any) - -const AuthenticatedLayoutTeamsGroupIdRoute = - AuthenticatedLayoutTeamsGroupIdImport.update({ - id: '/teams/$groupId', - path: '/teams/$groupId', - getParentRoute: () => AuthenticatedLayoutRoute, - } as any) - -const AuthenticatedLayoutProjectsProjectNameIdRoute = - AuthenticatedLayoutProjectsProjectNameIdImport.update({ - id: '/projects/$projectNameId', - path: '/projects/$projectNameId', - getParentRoute: () => AuthenticatedLayoutRoute, - } as any) - -const AuthenticatedLayoutMyProfileFeaturesRoute = - AuthenticatedLayoutMyProfileFeaturesImport.update({ - id: '/features', - path: '/features', - getParentRoute: () => AuthenticatedLayoutMyProfileRoute, - } as any) - -const AuthenticatedLayoutGamesSplatRoute = - AuthenticatedLayoutGamesSplatImport.update({ - id: '/games/$', - path: '/games/$', - getParentRoute: () => AuthenticatedLayoutRoute, - } as any) - -const AuthenticatedLayoutTeamsGroupIdIndexRoute = - AuthenticatedLayoutTeamsGroupIdIndexImport.update({ - id: '/', - path: '/', - getParentRoute: () => AuthenticatedLayoutTeamsGroupIdRoute, - } as any) - -const AuthenticatedLayoutProjectsProjectNameIdIndexRoute = - AuthenticatedLayoutProjectsProjectNameIdIndexImport.update({ - id: '/', - path: '/', - getParentRoute: () => AuthenticatedLayoutProjectsProjectNameIdRoute, - } as any) - -const AuthenticatedLayoutTeamsGroupIdSettingsRoute = - AuthenticatedLayoutTeamsGroupIdSettingsImport.update({ - id: '/settings', - path: '/settings', - getParentRoute: () => AuthenticatedLayoutTeamsGroupIdRoute, - } as any) - -const AuthenticatedLayoutTeamsGroupIdMembersRoute = - AuthenticatedLayoutTeamsGroupIdMembersImport.update({ - id: '/members', - path: '/members', - getParentRoute: () => AuthenticatedLayoutTeamsGroupIdRoute, - } as any) - -const AuthenticatedLayoutTeamsGroupIdBillingRoute = - AuthenticatedLayoutTeamsGroupIdBillingImport.update({ - id: '/billing', - path: '/billing', - getParentRoute: () => AuthenticatedLayoutTeamsGroupIdRoute, - } as any) - -const AuthenticatedLayoutProjectsProjectNameIdTokensRoute = - AuthenticatedLayoutProjectsProjectNameIdTokensImport.update({ - id: '/tokens', - path: '/tokens', - getParentRoute: () => AuthenticatedLayoutProjectsProjectNameIdRoute, - } as any) - -const AuthenticatedLayoutProjectsProjectNameIdSettingsRoute = - AuthenticatedLayoutProjectsProjectNameIdSettingsImport.update({ - id: '/settings', - path: '/settings', - getParentRoute: () => AuthenticatedLayoutProjectsProjectNameIdRoute, - } as any) - -const AuthenticatedLayoutProjectsProjectNameIdBillingRoute = - AuthenticatedLayoutProjectsProjectNameIdBillingImport.update({ - id: '/billing', - path: '/billing', - getParentRoute: () => AuthenticatedLayoutProjectsProjectNameIdRoute, - } as any) - -const AuthenticatedLayoutTeamsGroupIdSettingsIndexRoute = - AuthenticatedLayoutTeamsGroupIdSettingsIndexImport.update({ - id: '/', - path: '/', - getParentRoute: () => AuthenticatedLayoutTeamsGroupIdSettingsRoute, - } as any) - -const AuthenticatedLayoutProjectsProjectNameIdSettingsIndexRoute = - AuthenticatedLayoutProjectsProjectNameIdSettingsIndexImport.update({ - id: '/', - path: '/', - getParentRoute: () => AuthenticatedLayoutProjectsProjectNameIdSettingsRoute, - } as any) - -const AuthenticatedLayoutProjectsProjectNameIdNamespacesSplatRoute = - AuthenticatedLayoutProjectsProjectNameIdNamespacesSplatImport.update({ - id: '/namespaces/$', - path: '/namespaces/$', - getParentRoute: () => AuthenticatedLayoutProjectsProjectNameIdRoute, - } as any) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdImport.update( - { - id: '/environments/$environmentNameId', - path: '/environments/$environmentNameId', - getParentRoute: () => AuthenticatedLayoutProjectsProjectNameIdRoute, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdIndexRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdIndexImport.update( - { - id: '/', - path: '/', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRoute, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdVersionsRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdVersionsImport.update( - { - id: '/versions', - path: '/versions', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRoute, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdTokensRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdTokensImport.update( - { - id: '/tokens', - path: '/tokens', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRoute, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersImport.update( - { - id: '/servers', - path: '/servers', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRoute, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdMatchmakerRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdMatchmakerImport.update( - { - id: '/matchmaker', - path: '/matchmaker', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRoute, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesImport.update( - { - id: '/lobbies', - path: '/lobbies', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRoute, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdCdnRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdCdnImport.update( - { - id: '/cdn', - path: '/cdn', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRoute, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBuildsRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBuildsImport.update( - { - id: '/builds', - path: '/builds', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRoute, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendImport.update( - { - id: '/backend', - path: '/backend', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRoute, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2Route = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2Import.update( - { - id: '/_v2', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRoute, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesIndexRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesIndexImport.update( - { - id: '/', - path: '/', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesRoute, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendIndexRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendIndexImport.update( - { - id: '/', - path: '/', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendRoute, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersSplatRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersSplatImport.update( - { - id: '/$', - path: '/$', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersRoute, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesSettingsRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesSettingsImport.update( - { - id: '/settings', - path: '/settings', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesRoute, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesLogsRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesLogsImport.update( - { - id: '/logs', - path: '/logs', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesRoute, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendVariablesRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendVariablesImport.update( - { - id: '/variables', - path: '/variables', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendRoute, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendLogsRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendLogsImport.update( - { - id: '/logs', - path: '/logs', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendRoute, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2SettingsRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2SettingsImport.update( - { - id: '/settings', - path: '/settings', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2Route, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2LogsRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2LogsImport.update( - { - id: '/logs', - path: '/logs', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2Route, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2FunctionsRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2FunctionsImport.update( - { - id: '/functions', - path: '/functions', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2Route, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ContainersRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ContainersImport.update( - { - id: '/containers', - path: '/containers', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2Route, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorsRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorsImport.update( - { - id: '/actors', - path: '/actors', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2Route, - } as any, - ) - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorVersionsRoute = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorVersionsImport.update( - { - id: '/actor-versions', - path: '/actor-versions', - getParentRoute: () => - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2Route, - } as any, - ) - -// Populate the FileRoutesByPath interface - -declare module '@tanstack/react-router' { - interface FileRoutesByPath { - '/_authenticated': { - id: '/_authenticated' - path: '' - fullPath: '' - preLoaderRoute: typeof AuthenticatedImport - parentRoute: typeof rootRoute - } - '/_authenticated/_layout': { - id: '/_authenticated/_layout' - path: '' - fullPath: '' - preLoaderRoute: typeof AuthenticatedLayoutImport - parentRoute: typeof AuthenticatedImport - } - '/_authenticated/billing': { - id: '/_authenticated/billing' - path: '/billing' - fullPath: '/billing' - preLoaderRoute: typeof AuthenticatedBillingImport - parentRoute: typeof AuthenticatedImport - } - '/_authenticated/_layout/my-profile': { - id: '/_authenticated/_layout/my-profile' - path: '/my-profile' - fullPath: '/my-profile' - preLoaderRoute: typeof AuthenticatedLayoutMyProfileImport - parentRoute: typeof AuthenticatedLayoutImport - } - '/_authenticated/devices/link': { - id: '/_authenticated/devices/link' - path: '/devices/link' - fullPath: '/devices/link' - preLoaderRoute: typeof AuthenticatedDevicesLinkImport - parentRoute: typeof AuthenticatedImport - } - '/_authenticated/invite/$inviteCode': { - id: '/_authenticated/invite/$inviteCode' - path: '/invite/$inviteCode' - fullPath: '/invite/$inviteCode' - preLoaderRoute: typeof AuthenticatedInviteInviteCodeImport - parentRoute: typeof AuthenticatedImport - } - '/_authenticated/_layout/': { - id: '/_authenticated/_layout/' - path: '/' - fullPath: '/' - preLoaderRoute: typeof AuthenticatedLayoutIndexImport - parentRoute: typeof AuthenticatedLayoutImport - } - '/_authenticated/_layout/games/$': { - id: '/_authenticated/_layout/games/$' - path: '/games/$' - fullPath: '/games/$' - preLoaderRoute: typeof AuthenticatedLayoutGamesSplatImport - parentRoute: typeof AuthenticatedLayoutImport - } - '/_authenticated/_layout/my-profile/features': { - id: '/_authenticated/_layout/my-profile/features' - path: '/features' - fullPath: '/my-profile/features' - preLoaderRoute: typeof AuthenticatedLayoutMyProfileFeaturesImport - parentRoute: typeof AuthenticatedLayoutMyProfileImport - } - '/_authenticated/_layout/projects/$projectNameId': { - id: '/_authenticated/_layout/projects/$projectNameId' - path: '/projects/$projectNameId' - fullPath: '/projects/$projectNameId' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdImport - parentRoute: typeof AuthenticatedLayoutImport - } - '/_authenticated/_layout/teams/$groupId': { - id: '/_authenticated/_layout/teams/$groupId' - path: '/teams/$groupId' - fullPath: '/teams/$groupId' - preLoaderRoute: typeof AuthenticatedLayoutTeamsGroupIdImport - parentRoute: typeof AuthenticatedLayoutImport - } - '/_authenticated/devices/link_/$token': { - id: '/_authenticated/devices/link_/$token' - path: '/devices/link/$token' - fullPath: '/devices/link/$token' - preLoaderRoute: typeof AuthenticatedDevicesLinkTokenImport - parentRoute: typeof AuthenticatedImport - } - '/_authenticated/_layout/my-profile/': { - id: '/_authenticated/_layout/my-profile/' - path: '/' - fullPath: '/my-profile/' - preLoaderRoute: typeof AuthenticatedLayoutMyProfileIndexImport - parentRoute: typeof AuthenticatedLayoutMyProfileImport - } - '/_authenticated/_layout/projects/$projectNameId/billing': { - id: '/_authenticated/_layout/projects/$projectNameId/billing' - path: '/billing' - fullPath: '/projects/$projectNameId/billing' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdBillingImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdImport - } - '/_authenticated/_layout/projects/$projectNameId/settings': { - id: '/_authenticated/_layout/projects/$projectNameId/settings' - path: '/settings' - fullPath: '/projects/$projectNameId/settings' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdSettingsImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdImport - } - '/_authenticated/_layout/projects/$projectNameId/tokens': { - id: '/_authenticated/_layout/projects/$projectNameId/tokens' - path: '/tokens' - fullPath: '/projects/$projectNameId/tokens' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdTokensImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdImport - } - '/_authenticated/_layout/teams/$groupId/billing': { - id: '/_authenticated/_layout/teams/$groupId/billing' - path: '/billing' - fullPath: '/teams/$groupId/billing' - preLoaderRoute: typeof AuthenticatedLayoutTeamsGroupIdBillingImport - parentRoute: typeof AuthenticatedLayoutTeamsGroupIdImport - } - '/_authenticated/_layout/teams/$groupId/members': { - id: '/_authenticated/_layout/teams/$groupId/members' - path: '/members' - fullPath: '/teams/$groupId/members' - preLoaderRoute: typeof AuthenticatedLayoutTeamsGroupIdMembersImport - parentRoute: typeof AuthenticatedLayoutTeamsGroupIdImport - } - '/_authenticated/_layout/teams/$groupId/settings': { - id: '/_authenticated/_layout/teams/$groupId/settings' - path: '/settings' - fullPath: '/teams/$groupId/settings' - preLoaderRoute: typeof AuthenticatedLayoutTeamsGroupIdSettingsImport - parentRoute: typeof AuthenticatedLayoutTeamsGroupIdImport - } - '/_authenticated/_layout/projects/$projectNameId/': { - id: '/_authenticated/_layout/projects/$projectNameId/' - path: '/' - fullPath: '/projects/$projectNameId/' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdIndexImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdImport - } - '/_authenticated/_layout/teams/$groupId/': { - id: '/_authenticated/_layout/teams/$groupId/' - path: '/' - fullPath: '/teams/$groupId/' - preLoaderRoute: typeof AuthenticatedLayoutTeamsGroupIdIndexImport - parentRoute: typeof AuthenticatedLayoutTeamsGroupIdImport - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId' - path: '/environments/$environmentNameId' - fullPath: '/projects/$projectNameId/environments/$environmentNameId' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdImport - } - '/_authenticated/_layout/projects/$projectNameId/namespaces/$': { - id: '/_authenticated/_layout/projects/$projectNameId/namespaces/$' - path: '/namespaces/$' - fullPath: '/projects/$projectNameId/namespaces/$' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdNamespacesSplatImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdImport - } - '/_authenticated/_layout/projects/$projectNameId/settings/': { - id: '/_authenticated/_layout/projects/$projectNameId/settings/' - path: '/' - fullPath: '/projects/$projectNameId/settings/' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdSettingsIndexImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdSettingsImport - } - '/_authenticated/_layout/teams/$groupId/settings/': { - id: '/_authenticated/_layout/teams/$groupId/settings/' - path: '/' - fullPath: '/teams/$groupId/settings/' - preLoaderRoute: typeof AuthenticatedLayoutTeamsGroupIdSettingsIndexImport - parentRoute: typeof AuthenticatedLayoutTeamsGroupIdSettingsImport - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2' - path: '' - fullPath: '/projects/$projectNameId/environments/$environmentNameId' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2Import - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdImport - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend' - path: '/backend' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/backend' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdImport - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/builds': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/builds' - path: '/builds' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/builds' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBuildsImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdImport - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/cdn': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/cdn' - path: '/cdn' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/cdn' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdCdnImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdImport - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies' - path: '/lobbies' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/lobbies' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdImport - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/matchmaker': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/matchmaker' - path: '/matchmaker' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/matchmaker' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdMatchmakerImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdImport - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers' - path: '/servers' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/servers' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdImport - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/tokens': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/tokens' - path: '/tokens' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/tokens' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdTokensImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdImport - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/versions': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/versions' - path: '/versions' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/versions' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdVersionsImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdImport - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/' - path: '/' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdIndexImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdImport - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/actor-versions': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/actor-versions' - path: '/actor-versions' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/actor-versions' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorVersionsImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2Import - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/actors': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/actors' - path: '/actors' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/actors' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorsImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2Import - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/containers': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/containers' - path: '/containers' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/containers' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ContainersImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2Import - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/functions': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/functions' - path: '/functions' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/functions' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2FunctionsImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2Import - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/logs': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/logs' - path: '/logs' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/logs' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2LogsImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2Import - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/settings': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/settings' - path: '/settings' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/settings' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2SettingsImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2Import - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/logs': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/logs' - path: '/logs' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/backend/logs' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendLogsImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendImport - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/variables': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/variables' - path: '/variables' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/backend/variables' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendVariablesImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendImport - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/logs': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/logs' - path: '/logs' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/lobbies/logs' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesLogsImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesImport - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/settings': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/settings' - path: '/settings' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/lobbies/settings' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesSettingsImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesImport - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers/$': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers/$' - path: '/$' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/servers/$' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersSplatImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersImport - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/' - path: '/' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/backend/' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendIndexImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendImport - } - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/': { - id: '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/' - path: '/' - fullPath: '/projects/$projectNameId/environments/$environmentNameId/lobbies/' - preLoaderRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesIndexImport - parentRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesImport - } - } -} - -// Create and export the route tree - -interface AuthenticatedLayoutMyProfileRouteChildren { - AuthenticatedLayoutMyProfileFeaturesRoute: typeof AuthenticatedLayoutMyProfileFeaturesRoute - AuthenticatedLayoutMyProfileIndexRoute: typeof AuthenticatedLayoutMyProfileIndexRoute -} - -const AuthenticatedLayoutMyProfileRouteChildren: AuthenticatedLayoutMyProfileRouteChildren = - { - AuthenticatedLayoutMyProfileFeaturesRoute: - AuthenticatedLayoutMyProfileFeaturesRoute, - AuthenticatedLayoutMyProfileIndexRoute: - AuthenticatedLayoutMyProfileIndexRoute, - } - -const AuthenticatedLayoutMyProfileRouteWithChildren = - AuthenticatedLayoutMyProfileRoute._addFileChildren( - AuthenticatedLayoutMyProfileRouteChildren, - ) - -interface AuthenticatedLayoutProjectsProjectNameIdSettingsRouteChildren { - AuthenticatedLayoutProjectsProjectNameIdSettingsIndexRoute: typeof AuthenticatedLayoutProjectsProjectNameIdSettingsIndexRoute -} - -const AuthenticatedLayoutProjectsProjectNameIdSettingsRouteChildren: AuthenticatedLayoutProjectsProjectNameIdSettingsRouteChildren = - { - AuthenticatedLayoutProjectsProjectNameIdSettingsIndexRoute: - AuthenticatedLayoutProjectsProjectNameIdSettingsIndexRoute, - } - -const AuthenticatedLayoutProjectsProjectNameIdSettingsRouteWithChildren = - AuthenticatedLayoutProjectsProjectNameIdSettingsRoute._addFileChildren( - AuthenticatedLayoutProjectsProjectNameIdSettingsRouteChildren, - ) - -interface AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2RouteChildren { - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorVersionsRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorVersionsRoute - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorsRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorsRoute - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ContainersRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ContainersRoute - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2FunctionsRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2FunctionsRoute - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2LogsRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2LogsRoute - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2SettingsRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2SettingsRoute -} - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2RouteChildren: AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2RouteChildren = - { - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorVersionsRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorVersionsRoute, - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorsRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorsRoute, - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ContainersRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ContainersRoute, - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2FunctionsRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2FunctionsRoute, - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2LogsRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2LogsRoute, - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2SettingsRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2SettingsRoute, - } - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2RouteWithChildren = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2Route._addFileChildren( - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2RouteChildren, - ) - -interface AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendRouteChildren { - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendLogsRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendLogsRoute - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendVariablesRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendVariablesRoute - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendIndexRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendIndexRoute -} - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendRouteChildren: AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendRouteChildren = - { - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendLogsRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendLogsRoute, - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendVariablesRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendVariablesRoute, - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendIndexRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendIndexRoute, - } - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendRouteWithChildren = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendRoute._addFileChildren( - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendRouteChildren, - ) - -interface AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesRouteChildren { - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesLogsRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesLogsRoute - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesSettingsRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesSettingsRoute - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesIndexRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesIndexRoute -} - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesRouteChildren: AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesRouteChildren = - { - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesLogsRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesLogsRoute, - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesSettingsRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesSettingsRoute, - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesIndexRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesIndexRoute, - } - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesRouteWithChildren = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesRoute._addFileChildren( - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesRouteChildren, - ) - -interface AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersRouteChildren { - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersSplatRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersSplatRoute -} - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersRouteChildren: AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersRouteChildren = - { - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersSplatRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersSplatRoute, - } - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersRouteWithChildren = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersRoute._addFileChildren( - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersRouteChildren, - ) - -interface AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRouteChildren { - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2Route: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2RouteWithChildren - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendRouteWithChildren - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBuildsRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBuildsRoute - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdCdnRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdCdnRoute - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesRouteWithChildren - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdMatchmakerRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdMatchmakerRoute - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersRouteWithChildren - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdTokensRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdTokensRoute - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdVersionsRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdVersionsRoute - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdIndexRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdIndexRoute -} - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRouteChildren: AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRouteChildren = - { - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2Route: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2RouteWithChildren, - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendRouteWithChildren, - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBuildsRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBuildsRoute, - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdCdnRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdCdnRoute, - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesRouteWithChildren, - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdMatchmakerRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdMatchmakerRoute, - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersRouteWithChildren, - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdTokensRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdTokensRoute, - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdVersionsRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdVersionsRoute, - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdIndexRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdIndexRoute, - } - -const AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRouteWithChildren = - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRoute._addFileChildren( - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRouteChildren, - ) - -interface AuthenticatedLayoutProjectsProjectNameIdRouteChildren { - AuthenticatedLayoutProjectsProjectNameIdBillingRoute: typeof AuthenticatedLayoutProjectsProjectNameIdBillingRoute - AuthenticatedLayoutProjectsProjectNameIdSettingsRoute: typeof AuthenticatedLayoutProjectsProjectNameIdSettingsRouteWithChildren - AuthenticatedLayoutProjectsProjectNameIdTokensRoute: typeof AuthenticatedLayoutProjectsProjectNameIdTokensRoute - AuthenticatedLayoutProjectsProjectNameIdIndexRoute: typeof AuthenticatedLayoutProjectsProjectNameIdIndexRoute - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRoute: typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRouteWithChildren - AuthenticatedLayoutProjectsProjectNameIdNamespacesSplatRoute: typeof AuthenticatedLayoutProjectsProjectNameIdNamespacesSplatRoute -} - -const AuthenticatedLayoutProjectsProjectNameIdRouteChildren: AuthenticatedLayoutProjectsProjectNameIdRouteChildren = - { - AuthenticatedLayoutProjectsProjectNameIdBillingRoute: - AuthenticatedLayoutProjectsProjectNameIdBillingRoute, - AuthenticatedLayoutProjectsProjectNameIdSettingsRoute: - AuthenticatedLayoutProjectsProjectNameIdSettingsRouteWithChildren, - AuthenticatedLayoutProjectsProjectNameIdTokensRoute: - AuthenticatedLayoutProjectsProjectNameIdTokensRoute, - AuthenticatedLayoutProjectsProjectNameIdIndexRoute: - AuthenticatedLayoutProjectsProjectNameIdIndexRoute, - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRoute: - AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRouteWithChildren, - AuthenticatedLayoutProjectsProjectNameIdNamespacesSplatRoute: - AuthenticatedLayoutProjectsProjectNameIdNamespacesSplatRoute, - } - -const AuthenticatedLayoutProjectsProjectNameIdRouteWithChildren = - AuthenticatedLayoutProjectsProjectNameIdRoute._addFileChildren( - AuthenticatedLayoutProjectsProjectNameIdRouteChildren, - ) - -interface AuthenticatedLayoutTeamsGroupIdSettingsRouteChildren { - AuthenticatedLayoutTeamsGroupIdSettingsIndexRoute: typeof AuthenticatedLayoutTeamsGroupIdSettingsIndexRoute -} - -const AuthenticatedLayoutTeamsGroupIdSettingsRouteChildren: AuthenticatedLayoutTeamsGroupIdSettingsRouteChildren = - { - AuthenticatedLayoutTeamsGroupIdSettingsIndexRoute: - AuthenticatedLayoutTeamsGroupIdSettingsIndexRoute, - } - -const AuthenticatedLayoutTeamsGroupIdSettingsRouteWithChildren = - AuthenticatedLayoutTeamsGroupIdSettingsRoute._addFileChildren( - AuthenticatedLayoutTeamsGroupIdSettingsRouteChildren, - ) - -interface AuthenticatedLayoutTeamsGroupIdRouteChildren { - AuthenticatedLayoutTeamsGroupIdBillingRoute: typeof AuthenticatedLayoutTeamsGroupIdBillingRoute - AuthenticatedLayoutTeamsGroupIdMembersRoute: typeof AuthenticatedLayoutTeamsGroupIdMembersRoute - AuthenticatedLayoutTeamsGroupIdSettingsRoute: typeof AuthenticatedLayoutTeamsGroupIdSettingsRouteWithChildren - AuthenticatedLayoutTeamsGroupIdIndexRoute: typeof AuthenticatedLayoutTeamsGroupIdIndexRoute -} - -const AuthenticatedLayoutTeamsGroupIdRouteChildren: AuthenticatedLayoutTeamsGroupIdRouteChildren = - { - AuthenticatedLayoutTeamsGroupIdBillingRoute: - AuthenticatedLayoutTeamsGroupIdBillingRoute, - AuthenticatedLayoutTeamsGroupIdMembersRoute: - AuthenticatedLayoutTeamsGroupIdMembersRoute, - AuthenticatedLayoutTeamsGroupIdSettingsRoute: - AuthenticatedLayoutTeamsGroupIdSettingsRouteWithChildren, - AuthenticatedLayoutTeamsGroupIdIndexRoute: - AuthenticatedLayoutTeamsGroupIdIndexRoute, - } - -const AuthenticatedLayoutTeamsGroupIdRouteWithChildren = - AuthenticatedLayoutTeamsGroupIdRoute._addFileChildren( - AuthenticatedLayoutTeamsGroupIdRouteChildren, - ) - -interface AuthenticatedLayoutRouteChildren { - AuthenticatedLayoutMyProfileRoute: typeof AuthenticatedLayoutMyProfileRouteWithChildren - AuthenticatedLayoutIndexRoute: typeof AuthenticatedLayoutIndexRoute - AuthenticatedLayoutGamesSplatRoute: typeof AuthenticatedLayoutGamesSplatRoute - AuthenticatedLayoutProjectsProjectNameIdRoute: typeof AuthenticatedLayoutProjectsProjectNameIdRouteWithChildren - AuthenticatedLayoutTeamsGroupIdRoute: typeof AuthenticatedLayoutTeamsGroupIdRouteWithChildren -} - -const AuthenticatedLayoutRouteChildren: AuthenticatedLayoutRouteChildren = { - AuthenticatedLayoutMyProfileRoute: - AuthenticatedLayoutMyProfileRouteWithChildren, - AuthenticatedLayoutIndexRoute: AuthenticatedLayoutIndexRoute, - AuthenticatedLayoutGamesSplatRoute: AuthenticatedLayoutGamesSplatRoute, - AuthenticatedLayoutProjectsProjectNameIdRoute: - AuthenticatedLayoutProjectsProjectNameIdRouteWithChildren, - AuthenticatedLayoutTeamsGroupIdRoute: - AuthenticatedLayoutTeamsGroupIdRouteWithChildren, -} - -const AuthenticatedLayoutRouteWithChildren = - AuthenticatedLayoutRoute._addFileChildren(AuthenticatedLayoutRouteChildren) - -interface AuthenticatedRouteChildren { - AuthenticatedLayoutRoute: typeof AuthenticatedLayoutRouteWithChildren - AuthenticatedBillingRoute: typeof AuthenticatedBillingRoute - AuthenticatedDevicesLinkRoute: typeof AuthenticatedDevicesLinkRoute - AuthenticatedInviteInviteCodeRoute: typeof AuthenticatedInviteInviteCodeRoute - AuthenticatedDevicesLinkTokenRoute: typeof AuthenticatedDevicesLinkTokenRoute -} - -const AuthenticatedRouteChildren: AuthenticatedRouteChildren = { - AuthenticatedLayoutRoute: AuthenticatedLayoutRouteWithChildren, - AuthenticatedBillingRoute: AuthenticatedBillingRoute, - AuthenticatedDevicesLinkRoute: AuthenticatedDevicesLinkRoute, - AuthenticatedInviteInviteCodeRoute: AuthenticatedInviteInviteCodeRoute, - AuthenticatedDevicesLinkTokenRoute: AuthenticatedDevicesLinkTokenRoute, -} - -const AuthenticatedRouteWithChildren = AuthenticatedRoute._addFileChildren( - AuthenticatedRouteChildren, -) - -export interface FileRoutesByFullPath { - '': typeof AuthenticatedLayoutRouteWithChildren - '/billing': typeof AuthenticatedBillingRoute - '/my-profile': typeof AuthenticatedLayoutMyProfileRouteWithChildren - '/devices/link': typeof AuthenticatedDevicesLinkRoute - '/invite/$inviteCode': typeof AuthenticatedInviteInviteCodeRoute - '/': typeof AuthenticatedLayoutIndexRoute - '/games/$': typeof AuthenticatedLayoutGamesSplatRoute - '/my-profile/features': typeof AuthenticatedLayoutMyProfileFeaturesRoute - '/projects/$projectNameId': typeof AuthenticatedLayoutProjectsProjectNameIdRouteWithChildren - '/teams/$groupId': typeof AuthenticatedLayoutTeamsGroupIdRouteWithChildren - '/devices/link/$token': typeof AuthenticatedDevicesLinkTokenRoute - '/my-profile/': typeof AuthenticatedLayoutMyProfileIndexRoute - '/projects/$projectNameId/billing': typeof AuthenticatedLayoutProjectsProjectNameIdBillingRoute - '/projects/$projectNameId/settings': typeof AuthenticatedLayoutProjectsProjectNameIdSettingsRouteWithChildren - '/projects/$projectNameId/tokens': typeof AuthenticatedLayoutProjectsProjectNameIdTokensRoute - '/teams/$groupId/billing': typeof AuthenticatedLayoutTeamsGroupIdBillingRoute - '/teams/$groupId/members': typeof AuthenticatedLayoutTeamsGroupIdMembersRoute - '/teams/$groupId/settings': typeof AuthenticatedLayoutTeamsGroupIdSettingsRouteWithChildren - '/projects/$projectNameId/': typeof AuthenticatedLayoutProjectsProjectNameIdIndexRoute - '/teams/$groupId/': typeof AuthenticatedLayoutTeamsGroupIdIndexRoute - '/projects/$projectNameId/environments/$environmentNameId': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2RouteWithChildren - '/projects/$projectNameId/namespaces/$': typeof AuthenticatedLayoutProjectsProjectNameIdNamespacesSplatRoute - '/projects/$projectNameId/settings/': typeof AuthenticatedLayoutProjectsProjectNameIdSettingsIndexRoute - '/teams/$groupId/settings/': typeof AuthenticatedLayoutTeamsGroupIdSettingsIndexRoute - '/projects/$projectNameId/environments/$environmentNameId/backend': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendRouteWithChildren - '/projects/$projectNameId/environments/$environmentNameId/builds': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBuildsRoute - '/projects/$projectNameId/environments/$environmentNameId/cdn': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdCdnRoute - '/projects/$projectNameId/environments/$environmentNameId/lobbies': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesRouteWithChildren - '/projects/$projectNameId/environments/$environmentNameId/matchmaker': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdMatchmakerRoute - '/projects/$projectNameId/environments/$environmentNameId/servers': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersRouteWithChildren - '/projects/$projectNameId/environments/$environmentNameId/tokens': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdTokensRoute - '/projects/$projectNameId/environments/$environmentNameId/versions': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdVersionsRoute - '/projects/$projectNameId/environments/$environmentNameId/': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdIndexRoute - '/projects/$projectNameId/environments/$environmentNameId/actor-versions': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorVersionsRoute - '/projects/$projectNameId/environments/$environmentNameId/actors': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorsRoute - '/projects/$projectNameId/environments/$environmentNameId/containers': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ContainersRoute - '/projects/$projectNameId/environments/$environmentNameId/functions': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2FunctionsRoute - '/projects/$projectNameId/environments/$environmentNameId/logs': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2LogsRoute - '/projects/$projectNameId/environments/$environmentNameId/settings': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2SettingsRoute - '/projects/$projectNameId/environments/$environmentNameId/backend/logs': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendLogsRoute - '/projects/$projectNameId/environments/$environmentNameId/backend/variables': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendVariablesRoute - '/projects/$projectNameId/environments/$environmentNameId/lobbies/logs': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesLogsRoute - '/projects/$projectNameId/environments/$environmentNameId/lobbies/settings': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesSettingsRoute - '/projects/$projectNameId/environments/$environmentNameId/servers/$': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersSplatRoute - '/projects/$projectNameId/environments/$environmentNameId/backend/': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendIndexRoute - '/projects/$projectNameId/environments/$environmentNameId/lobbies/': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesIndexRoute -} - -export interface FileRoutesByTo { - '': typeof AuthenticatedRouteWithChildren - '/billing': typeof AuthenticatedBillingRoute - '/devices/link': typeof AuthenticatedDevicesLinkRoute - '/invite/$inviteCode': typeof AuthenticatedInviteInviteCodeRoute - '/': typeof AuthenticatedLayoutIndexRoute - '/games/$': typeof AuthenticatedLayoutGamesSplatRoute - '/my-profile/features': typeof AuthenticatedLayoutMyProfileFeaturesRoute - '/devices/link/$token': typeof AuthenticatedDevicesLinkTokenRoute - '/my-profile': typeof AuthenticatedLayoutMyProfileIndexRoute - '/projects/$projectNameId/billing': typeof AuthenticatedLayoutProjectsProjectNameIdBillingRoute - '/projects/$projectNameId/tokens': typeof AuthenticatedLayoutProjectsProjectNameIdTokensRoute - '/teams/$groupId/billing': typeof AuthenticatedLayoutTeamsGroupIdBillingRoute - '/teams/$groupId/members': typeof AuthenticatedLayoutTeamsGroupIdMembersRoute - '/projects/$projectNameId': typeof AuthenticatedLayoutProjectsProjectNameIdIndexRoute - '/teams/$groupId': typeof AuthenticatedLayoutTeamsGroupIdIndexRoute - '/projects/$projectNameId/namespaces/$': typeof AuthenticatedLayoutProjectsProjectNameIdNamespacesSplatRoute - '/projects/$projectNameId/settings': typeof AuthenticatedLayoutProjectsProjectNameIdSettingsIndexRoute - '/teams/$groupId/settings': typeof AuthenticatedLayoutTeamsGroupIdSettingsIndexRoute - '/projects/$projectNameId/environments/$environmentNameId': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdIndexRoute - '/projects/$projectNameId/environments/$environmentNameId/builds': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBuildsRoute - '/projects/$projectNameId/environments/$environmentNameId/cdn': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdCdnRoute - '/projects/$projectNameId/environments/$environmentNameId/matchmaker': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdMatchmakerRoute - '/projects/$projectNameId/environments/$environmentNameId/servers': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersRouteWithChildren - '/projects/$projectNameId/environments/$environmentNameId/tokens': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdTokensRoute - '/projects/$projectNameId/environments/$environmentNameId/versions': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdVersionsRoute - '/projects/$projectNameId/environments/$environmentNameId/actor-versions': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorVersionsRoute - '/projects/$projectNameId/environments/$environmentNameId/actors': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorsRoute - '/projects/$projectNameId/environments/$environmentNameId/containers': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ContainersRoute - '/projects/$projectNameId/environments/$environmentNameId/functions': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2FunctionsRoute - '/projects/$projectNameId/environments/$environmentNameId/logs': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2LogsRoute - '/projects/$projectNameId/environments/$environmentNameId/settings': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2SettingsRoute - '/projects/$projectNameId/environments/$environmentNameId/backend/logs': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendLogsRoute - '/projects/$projectNameId/environments/$environmentNameId/backend/variables': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendVariablesRoute - '/projects/$projectNameId/environments/$environmentNameId/lobbies/logs': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesLogsRoute - '/projects/$projectNameId/environments/$environmentNameId/lobbies/settings': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesSettingsRoute - '/projects/$projectNameId/environments/$environmentNameId/servers/$': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersSplatRoute - '/projects/$projectNameId/environments/$environmentNameId/backend': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendIndexRoute - '/projects/$projectNameId/environments/$environmentNameId/lobbies': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesIndexRoute -} - -export interface FileRoutesById { - __root__: typeof rootRoute - '/_authenticated': typeof AuthenticatedRouteWithChildren - '/_authenticated/_layout': typeof AuthenticatedLayoutRouteWithChildren - '/_authenticated/billing': typeof AuthenticatedBillingRoute - '/_authenticated/_layout/my-profile': typeof AuthenticatedLayoutMyProfileRouteWithChildren - '/_authenticated/devices/link': typeof AuthenticatedDevicesLinkRoute - '/_authenticated/invite/$inviteCode': typeof AuthenticatedInviteInviteCodeRoute - '/_authenticated/_layout/': typeof AuthenticatedLayoutIndexRoute - '/_authenticated/_layout/games/$': typeof AuthenticatedLayoutGamesSplatRoute - '/_authenticated/_layout/my-profile/features': typeof AuthenticatedLayoutMyProfileFeaturesRoute - '/_authenticated/_layout/projects/$projectNameId': typeof AuthenticatedLayoutProjectsProjectNameIdRouteWithChildren - '/_authenticated/_layout/teams/$groupId': typeof AuthenticatedLayoutTeamsGroupIdRouteWithChildren - '/_authenticated/devices/link_/$token': typeof AuthenticatedDevicesLinkTokenRoute - '/_authenticated/_layout/my-profile/': typeof AuthenticatedLayoutMyProfileIndexRoute - '/_authenticated/_layout/projects/$projectNameId/billing': typeof AuthenticatedLayoutProjectsProjectNameIdBillingRoute - '/_authenticated/_layout/projects/$projectNameId/settings': typeof AuthenticatedLayoutProjectsProjectNameIdSettingsRouteWithChildren - '/_authenticated/_layout/projects/$projectNameId/tokens': typeof AuthenticatedLayoutProjectsProjectNameIdTokensRoute - '/_authenticated/_layout/teams/$groupId/billing': typeof AuthenticatedLayoutTeamsGroupIdBillingRoute - '/_authenticated/_layout/teams/$groupId/members': typeof AuthenticatedLayoutTeamsGroupIdMembersRoute - '/_authenticated/_layout/teams/$groupId/settings': typeof AuthenticatedLayoutTeamsGroupIdSettingsRouteWithChildren - '/_authenticated/_layout/projects/$projectNameId/': typeof AuthenticatedLayoutProjectsProjectNameIdIndexRoute - '/_authenticated/_layout/teams/$groupId/': typeof AuthenticatedLayoutTeamsGroupIdIndexRoute - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdRouteWithChildren - '/_authenticated/_layout/projects/$projectNameId/namespaces/$': typeof AuthenticatedLayoutProjectsProjectNameIdNamespacesSplatRoute - '/_authenticated/_layout/projects/$projectNameId/settings/': typeof AuthenticatedLayoutProjectsProjectNameIdSettingsIndexRoute - '/_authenticated/_layout/teams/$groupId/settings/': typeof AuthenticatedLayoutTeamsGroupIdSettingsIndexRoute - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2RouteWithChildren - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendRouteWithChildren - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/builds': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBuildsRoute - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/cdn': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdCdnRoute - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesRouteWithChildren - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/matchmaker': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdMatchmakerRoute - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersRouteWithChildren - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/tokens': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdTokensRoute - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/versions': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdVersionsRoute - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdIndexRoute - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/actor-versions': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorVersionsRoute - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/actors': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ActorsRoute - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/containers': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2ContainersRoute - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/functions': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2FunctionsRoute - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/logs': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2LogsRoute - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/settings': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdV2SettingsRoute - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/logs': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendLogsRoute - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/variables': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendVariablesRoute - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/logs': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesLogsRoute - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/settings': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesSettingsRoute - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers/$': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdServersSplatRoute - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdBackendIndexRoute - '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/': typeof AuthenticatedLayoutProjectsProjectNameIdEnvironmentsEnvironmentNameIdLobbiesIndexRoute -} - -export interface FileRouteTypes { - fileRoutesByFullPath: FileRoutesByFullPath - fullPaths: - | '' - | '/billing' - | '/my-profile' - | '/devices/link' - | '/invite/$inviteCode' - | '/' - | '/games/$' - | '/my-profile/features' - | '/projects/$projectNameId' - | '/teams/$groupId' - | '/devices/link/$token' - | '/my-profile/' - | '/projects/$projectNameId/billing' - | '/projects/$projectNameId/settings' - | '/projects/$projectNameId/tokens' - | '/teams/$groupId/billing' - | '/teams/$groupId/members' - | '/teams/$groupId/settings' - | '/projects/$projectNameId/' - | '/teams/$groupId/' - | '/projects/$projectNameId/environments/$environmentNameId' - | '/projects/$projectNameId/namespaces/$' - | '/projects/$projectNameId/settings/' - | '/teams/$groupId/settings/' - | '/projects/$projectNameId/environments/$environmentNameId/backend' - | '/projects/$projectNameId/environments/$environmentNameId/builds' - | '/projects/$projectNameId/environments/$environmentNameId/cdn' - | '/projects/$projectNameId/environments/$environmentNameId/lobbies' - | '/projects/$projectNameId/environments/$environmentNameId/matchmaker' - | '/projects/$projectNameId/environments/$environmentNameId/servers' - | '/projects/$projectNameId/environments/$environmentNameId/tokens' - | '/projects/$projectNameId/environments/$environmentNameId/versions' - | '/projects/$projectNameId/environments/$environmentNameId/' - | '/projects/$projectNameId/environments/$environmentNameId/actor-versions' - | '/projects/$projectNameId/environments/$environmentNameId/actors' - | '/projects/$projectNameId/environments/$environmentNameId/containers' - | '/projects/$projectNameId/environments/$environmentNameId/functions' - | '/projects/$projectNameId/environments/$environmentNameId/logs' - | '/projects/$projectNameId/environments/$environmentNameId/settings' - | '/projects/$projectNameId/environments/$environmentNameId/backend/logs' - | '/projects/$projectNameId/environments/$environmentNameId/backend/variables' - | '/projects/$projectNameId/environments/$environmentNameId/lobbies/logs' - | '/projects/$projectNameId/environments/$environmentNameId/lobbies/settings' - | '/projects/$projectNameId/environments/$environmentNameId/servers/$' - | '/projects/$projectNameId/environments/$environmentNameId/backend/' - | '/projects/$projectNameId/environments/$environmentNameId/lobbies/' - fileRoutesByTo: FileRoutesByTo - to: - | '' - | '/billing' - | '/devices/link' - | '/invite/$inviteCode' - | '/' - | '/games/$' - | '/my-profile/features' - | '/devices/link/$token' - | '/my-profile' - | '/projects/$projectNameId/billing' - | '/projects/$projectNameId/tokens' - | '/teams/$groupId/billing' - | '/teams/$groupId/members' - | '/projects/$projectNameId' - | '/teams/$groupId' - | '/projects/$projectNameId/namespaces/$' - | '/projects/$projectNameId/settings' - | '/teams/$groupId/settings' - | '/projects/$projectNameId/environments/$environmentNameId' - | '/projects/$projectNameId/environments/$environmentNameId/builds' - | '/projects/$projectNameId/environments/$environmentNameId/cdn' - | '/projects/$projectNameId/environments/$environmentNameId/matchmaker' - | '/projects/$projectNameId/environments/$environmentNameId/servers' - | '/projects/$projectNameId/environments/$environmentNameId/tokens' - | '/projects/$projectNameId/environments/$environmentNameId/versions' - | '/projects/$projectNameId/environments/$environmentNameId/actor-versions' - | '/projects/$projectNameId/environments/$environmentNameId/actors' - | '/projects/$projectNameId/environments/$environmentNameId/containers' - | '/projects/$projectNameId/environments/$environmentNameId/functions' - | '/projects/$projectNameId/environments/$environmentNameId/logs' - | '/projects/$projectNameId/environments/$environmentNameId/settings' - | '/projects/$projectNameId/environments/$environmentNameId/backend/logs' - | '/projects/$projectNameId/environments/$environmentNameId/backend/variables' - | '/projects/$projectNameId/environments/$environmentNameId/lobbies/logs' - | '/projects/$projectNameId/environments/$environmentNameId/lobbies/settings' - | '/projects/$projectNameId/environments/$environmentNameId/servers/$' - | '/projects/$projectNameId/environments/$environmentNameId/backend' - | '/projects/$projectNameId/environments/$environmentNameId/lobbies' - id: - | '__root__' - | '/_authenticated' - | '/_authenticated/_layout' - | '/_authenticated/billing' - | '/_authenticated/_layout/my-profile' - | '/_authenticated/devices/link' - | '/_authenticated/invite/$inviteCode' - | '/_authenticated/_layout/' - | '/_authenticated/_layout/games/$' - | '/_authenticated/_layout/my-profile/features' - | '/_authenticated/_layout/projects/$projectNameId' - | '/_authenticated/_layout/teams/$groupId' - | '/_authenticated/devices/link_/$token' - | '/_authenticated/_layout/my-profile/' - | '/_authenticated/_layout/projects/$projectNameId/billing' - | '/_authenticated/_layout/projects/$projectNameId/settings' - | '/_authenticated/_layout/projects/$projectNameId/tokens' - | '/_authenticated/_layout/teams/$groupId/billing' - | '/_authenticated/_layout/teams/$groupId/members' - | '/_authenticated/_layout/teams/$groupId/settings' - | '/_authenticated/_layout/projects/$projectNameId/' - | '/_authenticated/_layout/teams/$groupId/' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId' - | '/_authenticated/_layout/projects/$projectNameId/namespaces/$' - | '/_authenticated/_layout/projects/$projectNameId/settings/' - | '/_authenticated/_layout/teams/$groupId/settings/' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/builds' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/cdn' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/matchmaker' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/tokens' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/versions' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/actor-versions' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/actors' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/containers' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/functions' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/logs' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/settings' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/logs' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/variables' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/logs' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/settings' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers/$' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/' - | '/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/' - fileRoutesById: FileRoutesById -} - -export interface RootRouteChildren { - AuthenticatedRoute: typeof AuthenticatedRouteWithChildren -} - -const rootRouteChildren: RootRouteChildren = { - AuthenticatedRoute: AuthenticatedRouteWithChildren, -} - -export const routeTree = rootRoute - ._addFileChildren(rootRouteChildren) - ._addFileTypes() - -/* ROUTE_MANIFEST_START -{ - "routes": { - "__root__": { - "filePath": "__root.tsx", - "children": [ - "/_authenticated" - ] - }, - "/_authenticated": { - "filePath": "_authenticated.tsx", - "children": [ - "/_authenticated/_layout", - "/_authenticated/billing", - "/_authenticated/devices/link", - "/_authenticated/invite/$inviteCode", - "/_authenticated/devices/link_/$token" - ] - }, - "/_authenticated/_layout": { - "filePath": "_authenticated/_layout.tsx", - "parent": "/_authenticated", - "children": [ - "/_authenticated/_layout/my-profile", - "/_authenticated/_layout/", - "/_authenticated/_layout/games/$", - "/_authenticated/_layout/projects/$projectNameId", - "/_authenticated/_layout/teams/$groupId" - ] - }, - "/_authenticated/billing": { - "filePath": "_authenticated/billing.tsx", - "parent": "/_authenticated" - }, - "/_authenticated/_layout/my-profile": { - "filePath": "_authenticated/_layout/my-profile.tsx", - "parent": "/_authenticated/_layout", - "children": [ - "/_authenticated/_layout/my-profile/features", - "/_authenticated/_layout/my-profile/" - ] - }, - "/_authenticated/devices/link": { - "filePath": "_authenticated/devices.link.tsx", - "parent": "/_authenticated" - }, - "/_authenticated/invite/$inviteCode": { - "filePath": "_authenticated/invite.$inviteCode.tsx", - "parent": "/_authenticated" - }, - "/_authenticated/_layout/": { - "filePath": "_authenticated/_layout/index.tsx", - "parent": "/_authenticated/_layout" - }, - "/_authenticated/_layout/games/$": { - "filePath": "_authenticated/_layout/games/$.tsx", - "parent": "/_authenticated/_layout" - }, - "/_authenticated/_layout/my-profile/features": { - "filePath": "_authenticated/_layout/my-profile/features.tsx", - "parent": "/_authenticated/_layout/my-profile" - }, - "/_authenticated/_layout/projects/$projectNameId": { - "filePath": "_authenticated/_layout/projects/$projectNameId.tsx", - "parent": "/_authenticated/_layout", - "children": [ - "/_authenticated/_layout/projects/$projectNameId/billing", - "/_authenticated/_layout/projects/$projectNameId/settings", - "/_authenticated/_layout/projects/$projectNameId/tokens", - "/_authenticated/_layout/projects/$projectNameId/", - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId", - "/_authenticated/_layout/projects/$projectNameId/namespaces/$" - ] - }, - "/_authenticated/_layout/teams/$groupId": { - "filePath": "_authenticated/_layout/teams/$groupId.tsx", - "parent": "/_authenticated/_layout", - "children": [ - "/_authenticated/_layout/teams/$groupId/billing", - "/_authenticated/_layout/teams/$groupId/members", - "/_authenticated/_layout/teams/$groupId/settings", - "/_authenticated/_layout/teams/$groupId/" - ] - }, - "/_authenticated/devices/link_/$token": { - "filePath": "_authenticated/devices.link_.$token.tsx", - "parent": "/_authenticated" - }, - "/_authenticated/_layout/my-profile/": { - "filePath": "_authenticated/_layout/my-profile/index.tsx", - "parent": "/_authenticated/_layout/my-profile" - }, - "/_authenticated/_layout/projects/$projectNameId/billing": { - "filePath": "_authenticated/_layout/projects/$projectNameId/billing.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId" - }, - "/_authenticated/_layout/projects/$projectNameId/settings": { - "filePath": "_authenticated/_layout/projects/$projectNameId/settings.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId", - "children": [ - "/_authenticated/_layout/projects/$projectNameId/settings/" - ] - }, - "/_authenticated/_layout/projects/$projectNameId/tokens": { - "filePath": "_authenticated/_layout/projects/$projectNameId/tokens.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId" - }, - "/_authenticated/_layout/teams/$groupId/billing": { - "filePath": "_authenticated/_layout/teams/$groupId/billing.tsx", - "parent": "/_authenticated/_layout/teams/$groupId" - }, - "/_authenticated/_layout/teams/$groupId/members": { - "filePath": "_authenticated/_layout/teams/$groupId/members.tsx", - "parent": "/_authenticated/_layout/teams/$groupId" - }, - "/_authenticated/_layout/teams/$groupId/settings": { - "filePath": "_authenticated/_layout/teams/$groupId/settings.tsx", - "parent": "/_authenticated/_layout/teams/$groupId", - "children": [ - "/_authenticated/_layout/teams/$groupId/settings/" - ] - }, - "/_authenticated/_layout/projects/$projectNameId/": { - "filePath": "_authenticated/_layout/projects/$projectNameId/index.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId" - }, - "/_authenticated/_layout/teams/$groupId/": { - "filePath": "_authenticated/_layout/teams/$groupId/index.tsx", - "parent": "/_authenticated/_layout/teams/$groupId" - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId", - "children": [ - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2", - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend", - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/builds", - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/cdn", - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies", - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/matchmaker", - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers", - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/tokens", - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/versions", - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/" - ] - }, - "/_authenticated/_layout/projects/$projectNameId/namespaces/$": { - "filePath": "_authenticated/_layout/projects/$projectNameId/namespaces/$.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId" - }, - "/_authenticated/_layout/projects/$projectNameId/settings/": { - "filePath": "_authenticated/_layout/projects/$projectNameId/settings/index.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/settings" - }, - "/_authenticated/_layout/teams/$groupId/settings/": { - "filePath": "_authenticated/_layout/teams/$groupId/settings/index.tsx", - "parent": "/_authenticated/_layout/teams/$groupId/settings" - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId", - "children": [ - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/actor-versions", - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/actors", - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/containers", - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/functions", - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/logs", - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/settings" - ] - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId", - "children": [ - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/logs", - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/variables", - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/" - ] - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/builds": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/builds.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId" - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/cdn": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/cdn.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId" - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId", - "children": [ - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/logs", - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/settings", - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/" - ] - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/matchmaker": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/matchmaker.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId" - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId", - "children": [ - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers/$" - ] - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/tokens": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/tokens.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId" - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/versions": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/versions.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId" - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/index.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId" - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/actor-versions": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/actor-versions.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2" - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/actors": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/actors.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2" - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/containers": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/containers.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2" - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/functions": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/functions.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2" - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/logs": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/logs.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2" - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/settings": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/settings.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2" - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/logs": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/logs.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend" - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/variables": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/variables.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend" - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/logs": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/logs.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies" - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/settings": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/settings.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies" - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers/$": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers/$.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers" - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/index.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend" - }, - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/": { - "filePath": "_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/index.tsx", - "parent": "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies" - } - } -} -ROUTE_MANIFEST_END */ diff --git a/frontend/apps/hub/src/routes/__root.tsx b/frontend/apps/hub/src/routes/__root.tsx deleted file mode 100644 index 6c560dd7e9..0000000000 --- a/frontend/apps/hub/src/routes/__root.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import { ErrorComponent } from "@/components/error-component"; -import { NotFoundComponent } from "@/components/not-found-component"; -import type { AuthContext } from "@/domains/auth/contexts/auth"; -import { useDialog } from "@/hooks/use-dialog"; -import * as Layout from "@/layouts/root"; -import { - FEEDBACK_FORM_ID, - FullscreenLoading, - Page, -} from "@rivet-gg/components"; -import { PageLayout } from "@rivet-gg/components/layout"; -import type { QueryClient } from "@tanstack/react-query"; -import { - type ErrorComponentProps, - Outlet, - createRootRouteWithContext, -} from "@tanstack/react-router"; -import { TanStackRouterDevtools } from "@tanstack/react-router-devtools"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { usePostHog } from "posthog-js/react"; -import { useKonami } from "react-konami-code"; -import { z } from "zod"; - -function Modals() { - const search = Route.useSearch(); - const navigate = Route.useNavigate(); - - const posthog = usePostHog(); - - const FeedbackDialog = useDialog.Feedback.Dialog; - const SecretDialog = useDialog.Secret.Dialog; - - useKonami(() => - navigate({ search: (old) => ({ ...old, modal: "secret" }) }), - ); - - const { modal, utm_source } = search; - - const handleOnOpenChange = (value: boolean) => { - if (!value) { - navigate({ search: (old) => ({ ...old, modal: undefined }) }); - } else { - posthog.capture("survey shown", { $survey_id: FEEDBACK_FORM_ID }); - } - }; - - return ( - <> - - - - ); -} - -function RootNotFoundComponent() { - return ( - - - - - - ); -} - -function RootErrorComponent(props: ErrorComponentProps) { - return ( - - - - - - ); -} - -function Root() { - return ( - - - - - - - - - - - ); -} - -function RootRoute() { - return ( - <> - - - {import.meta.env.DEV ? : null} - - ); -} - -export interface RouterContext { - auth: AuthContext; - queryClient: QueryClient; - subNav?: { title: string; url: string; exact?: boolean }[]; -} - -const searchSchema = z.object({ - modal: z.enum(["secret", "feedback"]).or(z.string()).optional(), - utm_source: z.string().optional(), -}); - -export const Route = createRootRouteWithContext()({ - validateSearch: zodValidator(searchSchema), - component: RootRoute, - errorComponent: RootErrorComponent, - notFoundComponent: RootNotFoundComponent, - pendingComponent: FullscreenLoading, - wrapInSuspense: true, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated.tsx b/frontend/apps/hub/src/routes/_authenticated.tsx deleted file mode 100644 index 7ea528e23c..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated.tsx +++ /dev/null @@ -1,103 +0,0 @@ -import { useAuth } from "@/domains/auth/contexts/auth"; -import { LoginView } from "@/domains/auth/views/login-view/login-view"; -import { useDialog } from "@/hooks/use-dialog"; -import * as Layout from "@/layouts/page-centered"; -import { FullscreenLoading } from "@rivet-gg/components"; -import { - Outlet, - createFileRoute, - retainSearchParams, - useNavigate, -} from "@tanstack/react-router"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { z } from "zod"; - -function Authenticated() { - const auth = useAuth(); - const navigate = useNavigate(); - - if (auth.isProfileLoading) { - return ; - } - - if (!auth.profile?.identity.isRegistered) { - return ( - - { - await auth.refreshToken(); - await navigate({ - to: "/", - }); - }} - /> - - ); - } - return ( - <> - - - - ); -} - -const searchSchema = z.object({ - modal: z.enum(["create-project", "create-group"]).or(z.string()).optional(), - groupId: z.string().optional().catch(undefined), -}); - -export const Route = createFileRoute("/_authenticated")({ - validateSearch: zodValidator(searchSchema), - component: Authenticated, - search: { - middlewares: [retainSearchParams(["modal"])], - }, -}); - -function Modals() { - const navigate = Route.useNavigate(); - const search = Route.useSearch(); - - const CreateGroupProjectDialog = useDialog.CreateProject.Dialog; - const CreateGroupDialog = useDialog.CreateGroup.Dialog; - - const { groupId, modal } = search; - - const handleOnOpenChange = (value: boolean) => { - if (!value) { - navigate({ search: { modal: undefined } }); - } - }; - return ( - <> - - await navigate({ - to: "/projects/$projectNameId", - params: { projectNameId: data.nameId }, - search: { modal: undefined }, - }) - } - dialogProps={{ - open: modal === "create-project", - onOpenChange: handleOnOpenChange, - }} - /> - - await navigate({ - to: "/teams/$groupId", - params: { groupId: data.groupId }, - search: { modal: undefined }, - }) - } - dialogProps={{ - open: modal === "create-group", - onOpenChange: handleOnOpenChange, - }} - /> - - ); -} diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout.tsx deleted file mode 100644 index 359673c8f1..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { computePageLayout } from "@/lib/compute-page-layout"; -import { PageLayout } from "@rivet-gg/components/layout"; -import { Outlet, createFileRoute, useMatches } from "@tanstack/react-router"; - -export const Route = createFileRoute("/_authenticated/_layout")({ - component: () => { - const matches = useMatches(); - return ( - - - - ); - }, - pendingComponent: PageLayout.Root.Skeleton, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/games/$.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/games/$.tsx deleted file mode 100644 index f514218bce..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/games/$.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { createFileRoute, redirect } from "@tanstack/react-router"; - -export const Route = createFileRoute("/_authenticated/_layout/games/$")({ - beforeLoad: ({ params, location }) => { - throw redirect({ - to: location.pathname.replace("/games/", "/projects/"), - }); - }, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/index.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/index.tsx deleted file mode 100644 index 2b82d1018d..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/index.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { Onboarding } from "@/components/onboarding/onboarding"; -import { GuardNewbie, guardOssNewbie } from "@/lib/guards"; -import { createFileRoute } from "@tanstack/react-router"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { z } from "zod"; - -function IndexRoute() { - const navigate = Route.useNavigate(); - const { initialStep, project_name: projectName } = Route.useSearch(); - return ( - { - return navigate({ - to: "/projects/$projectNameId/environments/$environmentNameId", - params: { - projectNameId: project.nameId, - environmentNameId: "prod", - }, - }); - }} - /> - ); -} - -const searchSchema = z.object({ - newbie: z.coerce.boolean().optional(), - initialStep: z.coerce.number().optional(), - project_name: z.coerce.string().optional(), -}); - -export const Route = createFileRoute("/_authenticated/_layout/")({ - validateSearch: zodValidator(searchSchema), - component: () => ( - - - - ), - staticData: { - layout: "onboarding", - }, - beforeLoad: ({ search, context: { queryClient, auth } }) => { - if (search.newbie === true) { - return; - } - return guardOssNewbie({ queryClient, auth }); - }, - shouldReload: true, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/my-profile.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/my-profile.tsx deleted file mode 100644 index 1f5dbe752b..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/my-profile.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as Layout from "@/domains/user/layouts/profile-layout"; -import { Outlet, createFileRoute } from "@tanstack/react-router"; - -function MyProfileRoute() { - return ( - - - - ); -} - -export const Route = createFileRoute("/_authenticated/_layout/my-profile")({ - component: MyProfileRoute, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/my-profile/features.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/my-profile/features.tsx deleted file mode 100644 index f7bd4561b5..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/my-profile/features.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { type FeatureFlag, useFeatureFlag } from "@/hooks/use-feature-flag"; -import { - Card, - CardContent, - CardHeader, - CardTitle, - Flex, - Strong, - Switch, - Text, -} from "@rivet-gg/components"; -import { createFileRoute } from "@tanstack/react-router"; -import { usePostHog } from "posthog-js/react"; -import type { ReactNode } from "react"; - -interface FeatureCardProps { - title: string; - description: ReactNode; - featureFlag: FeatureFlag; - onChanged: (enabled: boolean) => void; -} - -function FeatureCard({ - title, - description, - featureFlag, - onChanged, -}: FeatureCardProps) { - const isEnabled = useFeatureFlag(featureFlag); - return ( - - - - {title} - - - - {description} - - ); -} - -function MyProfileFeaturesRoute() { - const posthog = usePostHog(); - - return ( - <> - - Servers and Builds are the new way for managing your - project servers. They replace legacy namespaces and - versions. Turn this feature off to use the legacy - system. Not recommended for new users. - - } - featureFlag="hub-dynamic-servers" - onChanged={() => { - // FIXME: use internal properties api - }} - /> - - ); -} - -export const Route = createFileRoute( - "/_authenticated/_layout/my-profile/features", -)({ - component: MyProfileFeaturesRoute, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/my-profile/index.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/my-profile/index.tsx deleted file mode 100644 index 0ae4c0b803..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/my-profile/index.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { AccountDeletionCard } from "@/domains/user/components/account-deletion-card"; -import { UserAvatarSettingsCard } from "@/domains/user/components/user-avatar-settings-card"; -import { UserNameSettingsCard } from "@/domains/user/components/user-name-settings-card"; -import { createFileRoute } from "@tanstack/react-router"; - -function MyProfileIndexRoute() { - return ( - <> - - - - - ); -} - -export const Route = createFileRoute("/_authenticated/_layout/my-profile/")({ - component: MyProfileIndexRoute, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId.tsx deleted file mode 100644 index 707f09d5ce..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { ErrorComponent } from "@/components/error-component"; -import { BillingProvider } from "@/domains/project/components/billing/billing-context"; -import { BillingOverageWarning } from "@/domains/project/components/billing/billing-overage-warning"; -import { - ProjectContextProvider, - useProject, -} from "@/domains/project/data/project-context"; -import * as Layout from "@/domains/project/layouts/project-layout"; -import { useDialog } from "@/hooks/use-dialog"; -import { guardUuids } from "@/lib/guards"; - -import { - type ErrorComponentProps, - Outlet, - createFileRoute, -} from "@tanstack/react-router"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { z } from "zod"; - -function ProjectIdErrorComponent(props: ErrorComponentProps) { - return ( - - - - ); -} - -function Modals() { - const navigate = Route.useNavigate(); - const project = useProject(); - const { modal } = Route.useSearch(); - - const GenerateProjectCloudTokenDialog = - useDialog.GenerateProjectCloudToken.Dialog; - const CreateEnvironmentDialog = useDialog.CreateEnvironment.Dialog; - - const handleOnOpenChange = (value: boolean) => { - if (!value) { - navigate({ search: { modal: undefined } }); - } - }; - - return ( - <> - - - - ); -} - -function ProjectIdRoute() { - const { projectNameId } = Route.useParams(); - return ( - - - - - - - - - - ); -} - -const searchSchema = z.object({ - modal: z - .enum(["cloud-token", "service-token", "create-environment"]) - .or(z.string()) - .optional(), -}); - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId", -)({ - validateSearch: zodValidator(searchSchema), - component: ProjectIdRoute, - errorComponent: ProjectIdErrorComponent, - pendingComponent: Layout.Root.Skeleton, - beforeLoad: async ({ - matches, - location, - context: { queryClient, auth }, - params: { projectNameId }, - }) => { - await guardUuids({ - location, - queryClient, - projectNameId, - environmentNameId: undefined, - }); - }, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/billing.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/billing.tsx deleted file mode 100644 index eedd394704..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/billing.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { createFileRoute } from "@tanstack/react-router"; - -import { useProject } from "@/domains/project/data/project-context"; -import { BillingView } from "@/domains/project/views/billing-view"; -import { guardEnterprise } from "@/lib/guards"; - -function ProjectBillingRoute() { - const { gameId: projectId } = useProject(); - - return ; -} - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/billing", -)({ - beforeLoad: async ({ context: { queryClient } }) => { - await guardEnterprise({ queryClient }); - }, - component: ProjectBillingRoute, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/actor-versions.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/actor-versions.tsx deleted file mode 100644 index 32e924bee7..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/actor-versions.tsx +++ /dev/null @@ -1,301 +0,0 @@ -import { ErrorComponent } from "@/components/error-component"; -import { ProjectBuildsTableActions } from "@/domains/project/components/project-builds-table-actions"; -import { TagsSelect } from "@/domains/project/components/tags-select"; -import { useEnvironment } from "@/domains/project/data/environment-context"; -import { useProject } from "@/domains/project/data/project-context"; -import * as Layout from "@/domains/project/layouts/servers-layout"; -import { - projectBuildsQueryOptions, - projectCurrentBuildsQueryOptions, - usePatchActorBuildTagsMutation, - useUpgradeAllActorsMutation, -} from "@/domains/project/queries"; -import type { Rivet } from "@rivet-gg/api-full"; -import { - Button, - DiscreteCopyButton, - H1, - Skeleton, - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, - Text, - WithTooltip, -} from "@rivet-gg/components"; -import { ActorTags } from "@rivet-gg/components/actors"; -import { Icon, faCheckCircle, faInfoCircle, faRefresh } from "@rivet-gg/icons"; -import { useQuery, useSuspenseQuery } from "@tanstack/react-query"; -import { - type ErrorComponentProps, - createFileRoute, -} from "@tanstack/react-router"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { z } from "zod"; - -function ProjectBuildsRoute() { - const { gameId: projectId, nameId: projectNameId } = useProject(); - const { namespaceId: environmentId, nameId: environmentNameId } = - useEnvironment(); - - const search = Route.useSearch(); - const tags = "tags" in search ? Object.fromEntries(search.tags || []) : {}; - const { - data: builds, - isRefetching, - isLoading, - refetch, - } = useQuery(projectBuildsQueryOptions({ projectId, environmentId, tags })); - - const navigate = Route.useNavigate(); - - return ( - <> -
-

Builds

-
- { - navigate({ - search: { - tags: Object.entries(newTags).map( - ([key, value]) => - [key, value] as [string, string], - ), - }, - }); - }} - /> - -
-
- -
- -
-
-
- - - - ID - Name - - Tags - - - - Current{" "} - - - } - /> - - Created - - - - - {!isLoading && builds?.length === 0 ? ( - - - - There's no versions matching - criteria. - - - - ) : null} - {isLoading ? ( - <> - - - - - - - - - - ) : null} - {builds?.map((build) => ( - - - - {build.id.split("-")[0]} - - } - /> - - - - {build.tags.name} - - - - - - - - - - {build.createdAt.toLocaleString()} - - - - - - ))} - -
-
-
-
- - ); -} - -function RowSkeleton() { - return ( - - - - - - - - - - - - - - - - - - - - - ); -} - -interface ProjectBuildLatestButtonProps extends Rivet.builds.Build { - projectNameId: string; - environmentNameId: string; - projectId: string; - environmentId: string; -} - -function ProjectBuildLatestButton({ - tags, - id, - projectId, - environmentId, - projectNameId, - environmentNameId, -}: ProjectBuildLatestButtonProps) { - const { mutateAsync: mutateBuildTagsAsync } = - usePatchActorBuildTagsMutation(); - const { mutate: mutateUpgradeActors, isPending } = - useUpgradeAllActorsMutation(); - const { data: latestBuilds } = useSuspenseQuery( - projectCurrentBuildsQueryOptions({ projectId, environmentId }), - ); - - if (tags.current !== "true") { - return ( - - ); - } - - return ; -} - -const searchSchema = z.object({ - tags: z.array(z.tuple([z.string(), z.string()])).optional(), -}); - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/actor-versions", -)({ - validateSearch: zodValidator(searchSchema), - component: ProjectBuildsRoute, - staticData: { - layout: "v2", - }, - pendingComponent: () => ( -
- -
- ), - errorComponent(props: ErrorComponentProps) { - return ( -
-
- -
-
- ); - }, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/actors.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/actors.tsx deleted file mode 100644 index 4e003c313c..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/actors.tsx +++ /dev/null @@ -1,190 +0,0 @@ -import { ErrorComponent } from "@/components/error-component"; -import { ActorsActorDetailsWrapper } from "@/domains/project/components/actors/actors-actor-details-wrapper"; -import { ActorsProvider } from "@/domains/project/components/actors/actors-provider"; -import { useEnvironment } from "@/domains/project/data/environment-context"; -import { useProject } from "@/domains/project/data/project-context"; -import * as Layout from "@/domains/project/layouts/servers-layout"; -import { actorBuildsCountQueryOptions } from "@/domains/project/queries"; -import { useDialog } from "@/hooks/use-dialog"; -import { - ActorFeature, - ActorNotFound, - ActorsActorEmptyDetails, - ActorsListFiltersSchema, - ActorsListPreview, - currentActorAtom, - pickActorListFilters, -} from "@rivet-gg/components/actors"; -import { GettingStarted } from "@rivet-gg/components/actors"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { - type ErrorComponentProps, - createFileRoute, - useRouter, -} from "@tanstack/react-router"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { useAtomValue } from "jotai"; -import { z } from "zod"; -function Actor() { - const navigate = Route.useNavigate(); - const { tab } = Route.useSearch(); - - const actor = useAtomValue(currentActorAtom); - - if (!actor) { - return ( - - ); - } - - return ( - { - navigate({ - to: ".", - search: (old) => ({ ...old, tab }), - }); - }} - /> - ); -} - -const FIXED_TAGS = { - framework: "rivetkit", -}; -function Content() { - const { nameId: projectNameId } = useProject(); - const { nameId: environmentNameId } = useEnvironment(); - const { actorId, modal, ...restSearch } = Route.useSearch(); - - const CreateActorDialog = useDialog.CreateActor.Dialog; - const GoToActorDialog = useDialog.GoToActor.Dialog; - const router = useRouter(); - const navigate = Route.useNavigate(); - - function handleOpenChange(open: boolean) { - router.navigate({ - to: ".", - search: (old) => ({ - ...old, - modal: !open ? undefined : modal, - }), - }); - } - - const filters = pickActorListFilters(restSearch); - - return ( - - - {actorId ? ( - - ) : ( - - )} - - - - { - navigate({ - to: ".", - search: (old) => ({ - ...old, - actorId, - modal: undefined, - }), - }); - }} - dialogProps={{ - open: modal === "go-to-actor", - onOpenChange: handleOpenChange, - }} - /> - - ); -} - -function ProjectActorsRoute() { - const { nameId: projectNameId } = useProject(); - const { nameId: environmentNameId } = useEnvironment(); - const { tags, createdAt, destroyedAt } = Route.useSearch(); - - const { data } = useSuspenseQuery({ - ...actorBuildsCountQueryOptions({ - projectNameId, - environmentNameId, - }), - refetchInterval: (query) => - (query.state.data?.builds.length || 0) > 0 ? false : 2000, - }); - - if (data === 0 && !tags && !createdAt && !destroyedAt) { - return ; - } - - return ( -
- -
- ); -} - -const searchSchema = z - .object({ - actorId: z.string().optional(), - tab: z.string().optional(), - }) - .merge(ActorsListFiltersSchema); - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/actors", -)({ - validateSearch: zodValidator(searchSchema), - staticData: { - layout: "v2", - }, - component: ProjectActorsRoute, - pendingComponent: () => ( -
- -
- ), - errorComponent(props: ErrorComponentProps) { - return ( -
-
- -
-
- ); - }, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/containers.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/containers.tsx deleted file mode 100644 index 70234a06ed..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/containers.tsx +++ /dev/null @@ -1,237 +0,0 @@ -import { ErrorComponent } from "@/components/error-component"; -import { ActorsActorDetailsWrapper } from "@/domains/project/components/actors/actors-actor-details-wrapper"; -import { ActorsProvider } from "@/domains/project/components/actors/actors-provider"; -import { useEnvironment } from "@/domains/project/data/environment-context"; -import { useProject } from "@/domains/project/data/project-context"; -import * as Layout from "@/domains/project/layouts/servers-layout"; -import { actorBuildsCountQueryOptions } from "@/domains/project/queries"; -import { useDialog } from "@/hooks/use-dialog"; -import type { Rivet } from "@rivet-gg/api-full"; -import { toRecord } from "@rivet-gg/components"; -import { - ActorFeature, - ActorNotFound, - ActorsActorEmptyDetails, - ActorsListFiltersSchema, - ActorsListPreview, - ActorsViewContext, - type Actor as StateActor, - currentActorAtom, - pickActorListFilters, -} from "@rivet-gg/components/actors"; -import { GettingStarted } from "@rivet-gg/components/actors"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { - type ErrorComponentProps, - createFileRoute, - useRouter, -} from "@tanstack/react-router"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { useAtomValue } from "jotai"; -import { z } from "zod"; - -function Actor() { - const navigate = Route.useNavigate(); - const { tab } = Route.useSearch(); - - const actor = useAtomValue(currentActorAtom); - - if (!actor) { - return ( - - ); - } - - return ( - { - navigate({ - to: ".", - search: (old) => ({ ...old, tab }), - }); - }} - /> - ); -} - -const FIXED_TAGS = {}; - -const ACTORS_FILTER = (actor: Rivet.actors.Actor) => - toRecord(actor.tags).framework !== "rivetkit"; - -const ACTORS_VIEW_CONTEXT = { - copy: { - goToActor: "Go to Container", - selectActor: ( - <> - No Container selected. -
- - Select a Container from the list to view its details. - - - ), - showActorList: "Show Container list", - noActorsFound: "No Containers found", - createActor: "Create Container", - createActorUsingForm: "Create Container using simple form", - actorId: "Container ID", - noMoreActors: "No more Containers to load.", - noActorsMatchFilter: "No Containers match the filters.", - showHiddenActors: "Show hidden Containers", - - createActorModal: { - title: "Create Container", - description: - "Choose a build to create a Container from. Container will be created using default settings.", - }, - - actorNotFound: "Container not found", - actorNotFoundDescription: - "Change your filters to find the Container you are looking for.", - - gettingStarted: { - title: "Getting Started with Containers", - description: - "Use a quick start guide to start deploying Containers to your environment.", - }, - }, - canCreate: false, -}; - -const IS_ACTOR_INTERNAL = (actor: StateActor) => - toRecord(actor?.tags)?.type === "function"; - -function Content() { - const { nameId: projectNameId } = useProject(); - const { nameId: environmentNameId } = useEnvironment(); - const { actorId, modal, ...restSearch } = Route.useSearch(); - - const CreateActorDialog = useDialog.CreateActor.Dialog; - const GoToActorDialog = useDialog.GoToActor.Dialog; - const router = useRouter(); - const navigate = Route.useNavigate(); - - function handleOpenChange(open: boolean) { - router.navigate({ - to: ".", - search: (old) => ({ - ...old, - modal: !open ? undefined : modal, - }), - }); - } - - const filters = pickActorListFilters(restSearch); - - return ( - - - - {actorId ? ( - - ) : ( - - )} - - - - { - navigate({ - to: ".", - search: (old) => ({ - ...old, - actorId, - modal: undefined, - }), - }); - }} - dialogProps={{ - open: modal === "go-to-actor", - onOpenChange: handleOpenChange, - }} - /> - - - ); -} - -function ProjectActorsRoute() { - const { nameId: projectNameId } = useProject(); - const { nameId: environmentNameId } = useEnvironment(); - const { tags, createdAt, destroyedAt } = Route.useSearch(); - - const { data } = useSuspenseQuery({ - ...actorBuildsCountQueryOptions({ - projectNameId, - environmentNameId, - }), - refetchInterval: (query) => - (query.state.data?.builds.length || 0) > 0 ? false : 2000, - }); - - if (data === 0 && !tags && !createdAt && !destroyedAt) { - return ; - } - - return ( -
- -
- ); -} - -const searchSchema = z - .object({ - actorId: z.string().optional(), - tab: z.string().optional(), - }) - .merge(ActorsListFiltersSchema); - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/containers", -)({ - validateSearch: zodValidator(searchSchema), - staticData: { - layout: "v2", - }, - component: ProjectActorsRoute, - pendingComponent: () => ( -
- -
- ), - errorComponent(props: ErrorComponentProps) { - return ( -
-
- -
-
- ); - }, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/functions.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/functions.tsx deleted file mode 100644 index 6fa9bf1fcb..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/functions.tsx +++ /dev/null @@ -1,264 +0,0 @@ -import { ErrorComponent } from "@/components/error-component"; -import { useEnvironment } from "@/domains/project/data/environment-context"; -import { useProject } from "@/domains/project/data/project-context"; -import * as Layout from "@/domains/project/layouts/servers-layout"; -import { - projectActorsQueryOptions, - routesQueryOptions, - useDeleteRouteMutation, -} from "@/domains/project/queries"; -import { useDialog } from "@/hooks/use-dialog"; -import { - Button, - DiscreteCopyButton, - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, - H1, - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, - Text, -} from "@rivet-gg/components"; -import { Icon, faEllipsisH, faPlus } from "@rivet-gg/icons"; -import { - useInfiniteQuery, - usePrefetchInfiniteQuery, - useSuspenseQuery, -} from "@tanstack/react-query"; -import { - type ErrorComponentProps, - Link, - createFileRoute, -} from "@tanstack/react-router"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { z } from "zod"; - -function ProjectFunctionsRoute() { - const { projectNameId, environmentNameId } = Route.useParams(); - const { data: routes } = useSuspenseQuery( - routesQueryOptions(Route.useParams()), - ); - - usePrefetchInfiniteQuery({ - ...projectActorsQueryOptions({ - projectNameId, - environmentNameId, - includeDestroyed: false, - tags: {}, - }), - pages: 10, - }); - - const { data: actors } = useInfiniteQuery( - projectActorsQueryOptions({ - projectNameId, - environmentNameId, - includeDestroyed: false, - tags: {}, - }), - ); - - const navigate = Route.useNavigate(); - - const { mutate: deleteRoute } = useDeleteRouteMutation(); - - return ( - <> - - -
-

Functions

-
- -
-
- -
- -
-
-
- - - - Name - Route - - - - - {routes.length === 0 ? ( - - - - There's no routes yet. - - - - ) : null} - {routes?.map((route) => ( - - - - {route.id} - - - - - {`${route.hostname}${route.path}${route.routeSubpaths ? "/*" : ""}`} - - - - - - - - - - navigate({ - to: ".", - search: { - modal: "edit-route", - route: route.id, - }, - params: { - projectNameId, - environmentNameId, - }, - }) - } - > - Edit - - { - deleteRoute({ - projectNameId, - environmentNameId, - routeId: - route.id, - }); - }} - > - Delete - - - - - - ))} - -
-
-
-
- - ); -} - -function Modals() { - const navigate = Route.useNavigate(); - const { gameId: projectId, nameId: projectNameId } = useProject(); - const { namespaceId: environmentId, nameId: environmentNameId } = - useEnvironment(); - - const { modal, route } = Route.useSearch(); - - const EditRouteDialog = useDialog.EditRoute.Dialog; - const CreateRouteDialog = useDialog.CreateRoute.Dialog; - - const handleOnOpenChange = (value: boolean) => { - if (!value) { - navigate({ search: { modal: undefined } }); - } - }; - - return ( - <> - - - - ); -} - -const searchSchema = z.object({ - modal: z.enum(["add-route", "edit-route"]).or(z.string()).optional(), - route: z.string().optional(), -}); - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/functions", -)({ - validateSearch: zodValidator(searchSchema), - staticData: { - layout: "v2", - }, - component: ProjectFunctionsRoute, - pendingComponent: () => ( -
- -
- ), - errorComponent(props: ErrorComponentProps) { - return ( -
-
- -
-
- ); - }, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/logs.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/logs.tsx deleted file mode 100644 index 1de076ee58..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/logs.tsx +++ /dev/null @@ -1,641 +0,0 @@ -import { ErrorComponent } from "@/components/error-component"; -import * as Layout from "@/domains/project/layouts/servers-layout"; -import { - type FunctionInvoke, - logsAggregatedQueryOptions, - projectActorsQueryOptions, - routesQueryOptions, -} from "@/domains/project/queries"; -import { - Button, - Checkbox, - CommandGroup, - CommandItem, - FilterCreator, - type FilterDefinitions, - FilterOp, - type FilterValue, - LiveBadge, - type OnFiltersChange, - type OptionsProviderProps, - ShimmerLine, - SmallText, - ToggleGroup, - ToggleGroupItem, - VirtualScrollArea, - WithTooltip, - cn, - createFiltersPicker, - createFiltersSchema, - toRecord, -} from "@rivet-gg/components"; -import { - ActorObjectInspector, - ActorRegion, - ConsoleMessageVariantIcon, - getConsoleMessageVariant, - useActorsView, -} from "@rivet-gg/components/actors"; -import { - Icon, - faAngleDown, - faAngleUp, - faFontCase, - faKey, - faRegex, - faSignal, - faSwap, -} from "@rivet-gg/icons"; -import { - useInfiniteQuery, - usePrefetchInfiniteQuery, - useQuery, -} from "@tanstack/react-query"; -import { - type ErrorComponentProps, - Link, - createFileRoute, -} from "@tanstack/react-router"; -import type { Virtualizer } from "@tanstack/react-virtual"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { format } from "date-fns"; -import { forwardRef, useCallback, useRef, useState } from "react"; -import { useDebounceCallback } from "usehooks-ts"; -import { z } from "zod"; - -function ProjectFunctionsRoute() { - const { environmentNameId, projectNameId } = Route.useParams(); - - const navigate = Route.useNavigate(); - const { flags, search, ...restSearch } = Route.useSearch(); - - const filters = pickLogsFilters(restSearch) as Filters; - - usePrefetchInfiniteQuery({ - ...projectActorsQueryOptions({ - projectNameId, - environmentNameId, - includeDestroyed: true, - tags: {}, - }), - pages: 10, - }); - - const { data: actors } = useInfiniteQuery({ - ...projectActorsQueryOptions({ - projectNameId, - environmentNameId, - includeDestroyed: true, - tags: {}, - }), - }); - - const { data: rows, isLoading: isLoadingLogs } = useQuery( - logsAggregatedQueryOptions({ - projectNameId, - environmentNameId, - search: search - ? { - text: decodeURIComponent(search), - caseSensitive: - flags?.includes("case-sensitive") ?? false, - enableRegex: flags?.includes("regex") ?? false, - } - : undefined, - }), - ); - - const { data: routes } = useQuery( - routesQueryOptions({ - projectNameId, - environmentNameId, - }), - ); - - const searchInputRef = useRef(null); - - const onFiltersChange: OnFiltersChange = useCallback( - (fnOrValue) => { - if (typeof fnOrValue === "function") { - navigate({ - search: ({ search, flags, ...filters }) => ({ - search, - flags, - ...Object.fromEntries( - Object.entries(fnOrValue(filters)).filter( - ([, filter]) => filter.value.length > 0, - ), - ), - }), - }); - } else { - navigate({ - search: (value) => ({ - search: value.search, - flags: value.flags, - ...Object.fromEntries( - Object.entries(fnOrValue).filter( - ([, filter]) => filter.value.length > 0, - ), - ), - }), - }); - } - }, - [navigate], - ); - - const viewportRef = useRef(null); - const virtualizerRef = useRef>(null); - - // filter all rows by filters - const filteredRows = - rows?.filter((row) => { - const satisfiesFilters = Object.entries(filters).every( - ([key, filter]) => { - if (filter === undefined) return true; - - if (key === "level") { - const { operator, value } = filter; - if (operator === FilterOp.EQUAL) { - return value.includes(row.level as string); - } - if (operator === FilterOp.NOT_EQUAL) { - return value.length === 1 - ? row.level !== value[0] - : !value.includes(row.level as string); - } - } - - if (key === "routeId") { - const { operator, value } = filter; - const route = routes?.filter( - (route) => value.includes(route.id) && !!route, - ); - const actor = actors?.find( - (actor) => actor.id === row.actorId, - ); - - if (!route || !actor) return true; - - if (operator === FilterOp.EQUAL) { - return route.some((r) => { - return Object.entries( - r.target.actors?.selectorTags || {}, - ).some(([key, value]) => { - return toRecord(actor.tags)[key] === value; - }); - }); - } - if (operator === FilterOp.NOT_EQUAL) { - return route.every((r) => { - return Object.entries( - r.target.actors?.selectorTags || {}, - ).every(([key, value]) => { - return toRecord(actor.tags)[key] !== value; - }); - }); - } - } - - if (key === "actorId") { - const { operator, value } = filter; - const actor = actors?.find( - (actor) => actor.id === row.actorId, - ); - if (!actor) return true; - - if (operator === FilterOp.EQUAL) { - return value.includes(actor.id); - } - if (operator === FilterOp.NOT_EQUAL) { - return value.length === 1 - ? actor.id !== value[0] - : !value.includes(actor.id); - } - } - }, - ); - - return ( - satisfiesFilters && - row.line.toLowerCase().includes(search || "") - ); - }) ?? []; - - const setSearch = useDebounceCallback((search) => { - navigate({ - search: (value) => ({ - ...value, - search, - }), - }); - }, 500); - - const [expanded, setExpanded] = useState(() => [] as string[]); - - return ( -
-
- -
- setSearch(e.target.value)} - /> - { - navigate({ - search: (value) => ({ - ...value, - flags, - }), - }); - }} - > - - - - - - - -
- -
-
- ({ - ...filteredRows[index], - isExpanded: expanded.includes(filteredRows[index].id), - expand: () => - setExpanded((prev) => { - if (prev.includes(filteredRows[index].id)) { - return prev.filter( - (id) => id !== filteredRows[index].id, - ); - } - return [...prev, filteredRows[index].id]; - }), - })} - estimateSize={() => 28} - row={FunctionRow} - > - {isLoadingLogs ? ( - - ) : null} - {!isLoadingLogs && filteredRows?.length === 0 ? ( -
-

- No logs found. -

- - {Object.values(filters).length > 0 || - (search?.length || 0) > 0 ? ( - - ) : null} -
- ) : null} -
-
-
- ); -} - -const FunctionRow = forwardRef< - HTMLButtonElement, - FunctionInvoke & { - isExpanded: boolean; - expand: () => void; - className?: string; - } ->( - ( - { - id, - timestamp, - message, - line, - properties, - level, - actorId, - actorName, - regionId, - isFormatted, - isExpanded, - actorTags, - expand, - ...props - }, - ref, - ) => { - const { copy } = useActorsView(); - return ( - - ); - }, -); - -const ActorBadge = forwardRef< - HTMLButtonElement, - { - actorId: string; - actorName: string; - regionId: string; - actorTags: Record; - } ->(({ actorId, actorName, regionId, actorTags, ...props }, ref) => { - return ( - - ); -}); - -type Filters = { - level: FilterValue; - routeId: FilterValue; - actorId: FilterValue; -}; - -const FILTER_DEFINITIONS = { - level: { - label: "Level", - icon: faSignal, - type: "select", - options: [ - { label: "Info", value: "info" }, - { label: "Warning", value: "warning" }, - { label: "Error", value: "error" }, - ], - }, - routeId: { - label: "Route", - type: "select", - icon: faSwap, - options: RouteOptions, - }, - actorId: { - label: "Instance", - type: "select", - icon: faKey, - options: ActorOptions, - }, -} satisfies FilterDefinitions; - -export const LogsFiltersSchema = createFiltersSchema(FILTER_DEFINITIONS); - -export const pickLogsFilters = createFiltersPicker(FILTER_DEFINITIONS); - -function ActorOptions({ onSelect, value: filterValue }: OptionsProviderProps) { - const { environmentNameId, projectNameId } = Route.useParams(); - - const { data: actors = [] } = useInfiniteQuery( - projectActorsQueryOptions({ - projectNameId, - environmentNameId, - includeDestroyed: true, - tags: {}, - }), - ); - return ( - - {actors.map(({ id, ...actor }) => { - const isSelected = filterValue.some((val) => val === id); - - const name = toRecord(actor.tags).name as string; - return ( - { - if (isSelected) { - onSelect( - filterValue.filter( - (filterKey) => filterKey !== id, - ), - { closeAfter: true }, - ); - return; - } - - onSelect([...filterValue, id], { - closeAfter: true, - }); - }} - > - -
- - - {name ? ( - - {name} ({id.split("-")[0]}) - - ) : ( - id.split("-")[0] - )} -
-
- ); - })} -
- ); -} - -function RouteOptions({ onSelect, value: filterValue }: OptionsProviderProps) { - const { environmentNameId, projectNameId } = Route.useParams(); - const { data: routes = [] } = useQuery( - routesQueryOptions({ - projectNameId, - environmentNameId, - }), - ); - return ( - - {routes.map(({ id, ...route }) => { - const isSelected = filterValue.some((val) => val === id); - return ( - { - if (isSelected) { - onSelect( - filterValue.filter( - (filterKey) => filterKey !== id, - ), - { closeAfter: true }, - ); - return; - } - - onSelect([...filterValue, id], { - closeAfter: true, - }); - }} - > - - - {`${route.hostname}${route.path}${route.routeSubpaths ? "/*" : ""}`} - - - ); - })} - - ); -} - -const searchSchema = z - .object({ - search: z.string().optional(), - flags: z.array(z.enum(["case-sensitive", "regex"])).optional(), - }) - .merge(LogsFiltersSchema) - .strip(); - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/logs", -)({ - validateSearch: zodValidator(searchSchema), - staticData: { - layout: "v2", - }, - component: ProjectFunctionsRoute, - pendingComponent: Layout.Content.Skeleton, - errorComponent(props: ErrorComponentProps) { - return ( -
-
- -
-
- ); - }, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/settings.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/settings.tsx deleted file mode 100644 index 29a2921fbf..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId._v2/settings.tsx +++ /dev/null @@ -1,113 +0,0 @@ -import { ErrorComponent } from "@/components/error-component"; -import { useEnvironment } from "@/domains/project/data/environment-context"; -import { useProject } from "@/domains/project/data/project-context"; -import * as Layout from "@/domains/project/layouts/project-layout"; -import { useDialog } from "@/hooks/use-dialog"; -import { ActionCard, Button, H1, Text } from "@rivet-gg/components"; -import { - type ErrorComponentProps, - Link, - createFileRoute, -} from "@tanstack/react-router"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { z } from "zod"; - -function EnvironmentSettingsRoute() { - return ( - <> -
-

Settings

-
- -
-
-
- - -
-
- - ); -} - -function ServiceTokenCard() { - return ( - <> - - - Generate - - - } - > - - Service tokens are used from private API servers. These - should never be shared. - - - - ); -} - -function Modals() { - const navigate = Route.useNavigate(); - const { gameId: projectId, nameId: projectNameId } = useProject(); - const { namespaceId: environmentId, nameId: environmentNameId } = - useEnvironment(); - - const { modal } = Route.useSearch(); - - const GenerateProjectEnvServiceTokenDialog = - useDialog.GenerateProjectEnvServiceToken.Dialog; - - const handleOnOpenChange = (value: boolean) => { - if (!value) { - navigate({ search: { modal: undefined } }); - } - }; - - return ( - <> - - - ); -} - -const searchSchema = z.object({ - modal: z.enum(["service-token"]).or(z.string()).optional(), -}); - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2/settings", -)({ - staticData: { - layout: "v2", - }, - validateSearch: zodValidator(searchSchema), - component: EnvironmentSettingsRoute, - pendingComponent: () => ( -
- -
- ), - errorComponent(props: ErrorComponentProps) { - return ( -
-
- -
-
- ); - }, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId.tsx deleted file mode 100644 index 91ccb9075f..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId.tsx +++ /dev/null @@ -1,115 +0,0 @@ -import { ErrorComponent } from "@/components/error-component"; -import { - EnvironmentContextProvider, - useEnvironment, -} from "@/domains/project/data/environment-context"; -import { useProject } from "@/domains/project/data/project-context"; -import * as Layout from "@/domains/project/layouts/project-layout"; -import { useDialog } from "@/hooks/use-dialog"; -import { usePageLayout } from "@/lib/compute-page-layout"; -import { guardUuids } from "@/lib/guards"; -import { - type ErrorComponentProps, - Outlet, - createFileRoute, -} from "@tanstack/react-router"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { z } from "zod"; - -function Modals() { - const navigate = Route.useNavigate(); - const { gameId: projectId, nameId: projectNameId } = useProject(); - const { namespaceId: environmentId, nameId: environmentNameId } = - useEnvironment(); - const { modal, buildId } = Route.useSearch(); - - const ConfirmOuterbaseConnectionDialog = - useDialog.ConfirmOuterbaseConnection.Dialog; - - const EditBuildTagsDialog = useDialog.EditBuildTags.Dialog; - - const handleOpenChange = (value: boolean) => { - if (!value) { - navigate({ - to: ".", - search: (old) => ({ ...old, modal: undefined }), - }); - } - }; - - return ( - <> - - - - ); -} - -function EnvironmentErrorComponent(props: ErrorComponentProps) { - const layout = usePageLayout(); - - if (layout === "v2") { - return ( -
-
- -
-
- ); - } - return ; -} - -function environmentIdRoute() { - const { environmentNameId } = Route.useParams(); - return ( - - - - - ); -} -const searchSchema = z.object({ - modal: z - .enum(["database", "edit-tags", "create-actor", "go-to-actor"]) - .or(z.string()) - .optional(), - buildId: z.string().optional().catch(undefined), -}); -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId", -)({ - validateSearch: zodValidator(searchSchema), - beforeLoad: async ({ - matches, - location, - params: { projectNameId, environmentNameId }, - context: { queryClient }, - }) => { - await guardUuids({ - queryClient, - location, - projectNameId, - environmentNameId, - }); - }, - component: environmentIdRoute, - errorComponent: EnvironmentErrorComponent, - pendingComponent: Layout.Root.Skeleton, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2.tsx deleted file mode 100644 index 3a4be9a5cc..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2.tsx +++ /dev/null @@ -1,166 +0,0 @@ -import { Button, cn } from "@rivet-gg/components"; -import { ActorsLayout, useActorsLayout } from "@rivet-gg/components/actors"; -import { - Icon, - type IconProp, - faActorsBorderless, - faBarsStaggered, - faCodeBranch, - faCog, - faFunction, - faServer, - faSidebar, -} from "@rivet-gg/icons"; -import { Link, Outlet, createFileRoute } from "@tanstack/react-router"; -import { motion } from "framer-motion"; - -const SIDEBAR: { - label: string; - items: { - icon: IconProp; - label: string; - to: string; - isDisabled?: boolean; - }[]; -}[] = [ - { - label: "products", - items: [ - { icon: faActorsBorderless, label: "Actors", to: "actors" }, - { icon: faServer, label: "Containers", to: "containers" }, - { icon: faFunction, label: "Functions", to: "functions" }, - ], - }, - { - label: "tools", - items: [ - { icon: faBarsStaggered, label: "Logs", to: "logs" }, - { icon: faCodeBranch, label: "Versions", to: "actor-versions" }, - ], - }, - { - label: "settings", - items: [{ icon: faCog, label: "Settings", to: "settings" }], - }, -]; - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/_v2", -)({ - component: RouteComponent, -}); - -function RouteComponent() { - return ( - <> - } - right={ -
- -
- } - /> - - ); -} - -function Sidebar() { - const { isFolded, setFolded } = useActorsLayout(); - return ( - -
-
    - {SIDEBAR.map((item, index) => { - if ("items" in item) { - return ( -
  • -
      - {item.items.map((subItem, subIndex) => { - return ( -
    • - - {({ isActive }) => { - return ( - - ); - }} - -
    • - ); - })} -
    - - {index !== SIDEBAR.length - 1 && ( -
    - )} -
  • - ); - } - })} -
-
-
- -
-
- ); -} - -function SidebarItem({ - isActive, - label, - icon, -}: { isActive: boolean; label: string; icon: IconProp }) { - const { isFolded, setFolded } = useActorsLayout(); - return ( - - ); -} diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend.tsx deleted file mode 100644 index e11fd16ec5..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { ErrorComponent } from "@/components/error-component"; -import { useEnvironment } from "@/domains/project/data/environment-context"; -import { useProject } from "@/domains/project/data/project-context"; -import * as Layout from "@/domains/project/layouts/backend-layout"; -import { guardEnterprise } from "@/lib/guards"; -import { - type ErrorComponentProps, - Outlet, - createFileRoute, -} from "@tanstack/react-router"; - -function BackendLayoutErrorComponent(props: ErrorComponentProps) { - const { namespaceId: environmentId, nameId: environmentNameId } = - useEnvironment(); - const { gameId: projectId, nameId: projectNameId } = useProject(); - - return ( - - - - ); -} - -function BackendLayoutView() { - const { namespaceId: environmentId, nameId: environmentNameId } = - useEnvironment(); - const { gameId: projectId, nameId: projectNameId } = useProject(); - - return ( - - - - ); -} - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend", -)({ - component: BackendLayoutView, - errorComponent: BackendLayoutErrorComponent, - pendingComponent: Layout.Root.Skeleton, - beforeLoad: async ({ context: { queryClient } }) => { - await guardEnterprise({ queryClient }); - }, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/index.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/index.tsx deleted file mode 100644 index ed5a36cf3e..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/index.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { useEnvironment } from "@/domains/project/data/environment-context"; -import { useProject } from "@/domains/project/data/project-context"; -import * as Layout from "@/domains/project/layouts/backend-layout"; -import { ProjectBackendEnvironmentOverview } from "@/domains/project/views/environment-overview"; -import { createFileRoute } from "@tanstack/react-router"; - -function ProjectBackendEnvironmentIdOverviewRoute() { - const { namespaceId: environmentId } = useEnvironment(); - const { gameId: projectId } = useProject(); - - return ( - - ); -} - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/", -)({ - component: ProjectBackendEnvironmentIdOverviewRoute, - pendingComponent: Layout.Content.Skeleton, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/logs.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/logs.tsx deleted file mode 100644 index 9688e4e662..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/logs.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import { ErrorComponent } from "@/components/error-component"; -import { BackendListEventsPreview } from "@/domains/project/components/backend/backend-list-events-preview"; -import { useEnvironment } from "@/domains/project/data/environment-context"; -import { useProject } from "@/domains/project/data/project-context"; -import * as Layout from "@/domains/project/layouts/backend-layout"; -import { projectBackendEnvEventsQueryOptions } from "@/domains/project/queries"; -import { - Card, - CardContent, - CardHeader, - CardTitle, - LiveBadge, -} from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { - type ErrorComponentProps, - createFileRoute, -} from "@tanstack/react-router"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { z } from "zod"; - -function ProjectBackendEnvironmentIdLogsRoute() { - const { namespaceId: environmentId } = useEnvironment(); - const { gameId: projectId } = useProject(); - const { eventId } = Route.useSearch(); - - const { data } = useSuspenseQuery( - projectBackendEnvEventsQueryOptions({ - projectId, - environmentId: environmentId, - }), - ); - - return ( - - - - Logs - - - - - - - - ); -} - -const searchSchema = z.object({ - eventId: z.string().optional(), -}); - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/logs", -)({ - validateSearch: zodValidator(searchSchema), - staticData: { - layout: "full", - }, - component: ProjectBackendEnvironmentIdLogsRoute, - errorComponent: (props: ErrorComponentProps) => { - return ; - }, - pendingComponent: Layout.Content.Skeleton, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/variables.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/variables.tsx deleted file mode 100644 index 98b91cc0da..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/variables.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { useEnvironment } from "@/domains/project/data/environment-context"; -import { useProject } from "@/domains/project/data/project-context"; -import * as Layout from "@/domains/project/layouts/backend-layout"; -import { ProjectBackendEnvironmentVariables } from "@/domains/project/views/environment-variables"; -import { createFileRoute } from "@tanstack/react-router"; - -function ProjectBackendEnvironmentIdVariablesRoute() { - const { namespaceId: environmentId } = useEnvironment(); - const { gameId: projectId } = useProject(); - - return ( - - ); -} - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/backend/variables", -)({ - component: ProjectBackendEnvironmentIdVariablesRoute, - pendingComponent: Layout.Content.Skeleton, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/builds.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/builds.tsx deleted file mode 100644 index 40ea9fcfd9..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/builds.tsx +++ /dev/null @@ -1,272 +0,0 @@ -import { ProjectBuildsTableActions } from "@/domains/project/components/project-builds-table-actions"; -import { TagsSelect } from "@/domains/project/components/tags-select"; -import { useEnvironment } from "@/domains/project/data/environment-context"; -import { useProject } from "@/domains/project/data/project-context"; -import * as Layout from "@/domains/project/layouts/servers-layout"; -import { - projectBuildsQueryOptions, - projectCurrentBuildsQueryOptions, - usePatchActorBuildTagsMutation, - useUpgradeAllActorsMutation, -} from "@/domains/project/queries"; -import type { Rivet } from "@rivet-gg/api-full"; -import { - Button, - Card, - CardContent, - CardHeader, - CardTitle, - DiscreteCopyButton, - Flex, - Skeleton, - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, - Text, - WithTooltip, -} from "@rivet-gg/components"; -import { ActorTags } from "@rivet-gg/components/actors"; -import { Icon, faCheckCircle, faInfoCircle, faRefresh } from "@rivet-gg/icons"; -import { useQuery, useSuspenseQuery } from "@tanstack/react-query"; -import { createFileRoute } from "@tanstack/react-router"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { z } from "zod"; - -function ProjectBuildsRoute() { - const { gameId: projectId, nameId: projectNameId } = useProject(); - const { namespaceId: environmentId, nameId: environmentNameId } = - useEnvironment(); - - const search = Route.useSearch(); - const tags = "tags" in search ? Object.fromEntries(search.tags || []) : {}; - const { - data: builds, - isRefetching, - isLoading, - refetch, - } = useQuery(projectBuildsQueryOptions({ projectId, environmentId, tags })); - - const navigate = Route.useNavigate(); - - return ( - - - - Builds -
- { - navigate({ - search: { - tags: Object.entries(newTags).map( - ([key, value]) => - [key, value] as [ - string, - string, - ], - ), - }, - }); - }} - /> - -
-
-
- - - - - ID - Name - Tags - - - Current - - } - /> - - Created - - - - - {!isLoading && builds?.length === 0 ? ( - - - - There's no builds matching criteria. - - - - ) : null} - {isLoading ? ( - <> - - - - - - - - - - ) : null} - {builds?.map((build) => ( - - - - {build.id.split("-")[0]} - - } - /> - - - - {build.tags.name} - - - - - - - - - - {build.createdAt.toLocaleString()} - - - - - - ))} - -
-
-
- ); -} - -function RowSkeleton() { - return ( - - - - - - - - - - - - - - - - - - - - - ); -} - -interface ProjectBuildLatestButtonProps extends Rivet.builds.Build { - projectNameId: string; - environmentNameId: string; - projectId: string; - environmentId: string; -} - -function ProjectBuildLatestButton({ - tags, - id, - projectId, - environmentId, - projectNameId, - environmentNameId, -}: ProjectBuildLatestButtonProps) { - const { mutateAsync: mutateBuildTagsAsync } = - usePatchActorBuildTagsMutation(); - const { mutate: mutateUpgradeActors, isPending } = - useUpgradeAllActorsMutation(); - const { data: latestBuilds } = useSuspenseQuery( - projectCurrentBuildsQueryOptions({ projectId, environmentId }), - ); - - if (tags.current !== "true") { - return ( - - ); - } - - return ; -} - -const searchSchema = z.object({ - tags: z.array(z.tuple([z.string(), z.string()])).optional(), -}); - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/builds", -)({ - validateSearch: zodValidator(searchSchema), - component: ProjectBuildsRoute, - pendingComponent: Layout.Content.Skeleton, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/cdn.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/cdn.tsx deleted file mode 100644 index 41a1a32945..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/cdn.tsx +++ /dev/null @@ -1,212 +0,0 @@ -import { useEnvironment } from "@/domains/project/data/environment-context"; -import { useProject } from "@/domains/project/data/project-context"; -import { - projectEnvironmentQueryOptions, - useEnvironmentAuthTypeMutation, - useEnvironmentDomainPublicAuthMutation, -} from "@/domains/project/queries"; -import { useDialog } from "@/hooks/use-dialog"; -import { Rivet } from "@rivet-gg/api-full"; -import { - ActionCard, - Button, - Code, - Grid, - Ol, - Switch, - Text, -} from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { Link, createFileRoute } from "@tanstack/react-router"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { z } from "zod"; - -function DomainBasedAuthOption() { - const { mutate, isPending } = useEnvironmentDomainPublicAuthMutation(); - - const { namespaceId: environmentId } = useEnvironment(); - const { gameId: projectId } = useProject(); - - const { - data: { namespace: environment }, - } = useSuspenseQuery( - projectEnvironmentQueryOptions({ projectId, environmentId }), - ); - - return ( - { - mutate({ enabled, projectId, environmentId }); - }} - /> - } - > - - Allows for clients to authenticate with this environment based - on the domain they make requests from. This should only be used - for environments intended to be publicly accessible. - - - ); -} - -function PasswordAuthOption() { - const { mutate, isPending } = useEnvironmentAuthTypeMutation(); - - const { namespaceId: environmentId } = useEnvironment(); - const { gameId: projectId } = useProject(); - - const { - data: { namespace: environment }, - } = useSuspenseQuery( - projectEnvironmentQueryOptions({ projectId, environmentId }), - ); - - return ( - <> - { - mutate({ - authType: enabled - ? Rivet.cloud.CdnAuthType.Basic - : Rivet.cloud.CdnAuthType.None, - projectId, - environmentId, - }); - }} - /> - } - footer={ - - } - > - - Restricts CDN access to select authenticated users. - Authentication is done via HTTP basic access authentication. - - - - ); -} - -interface CustomDomainsOptionProps { - nameId: string; - namespaceNameId: string; -} - -function CustomDomainsOption({ - nameId, - namespaceNameId, -}: CustomDomainsOptionProps) { - return ( - <> - - - Manage domains - - - } - > -
    -
  1. - Add a CNAME record pointed at{" "} - - {nameId}--{namespaceNameId}.rivet.project - {" "} - to your domain's DNS config. -
  2. -
  3. Add your domain below.
  4. -
  5. - Once added, your domain will be verified by Cloudflare. - This should take around 5 minutes. -
  6. -
-
- - ); -} - -function Modals() { - const navigate = Route.useNavigate(); - const { namespaceId: environmentId } = useEnvironment(); - const { gameId: projectId } = useProject(); - const { modal } = Route.useSearch(); - - const ManageCdnAuthUsersDialog = useDialog.ManageCdnAuthUsers.Dialog; - const ManageCdnCustomDomains = useDialog.ManageCdnCustomDomains.Dialog; - - const handleOnOpenChange = (value: boolean) => { - if (!value) { - navigate({ search: { modal: undefined } }); - } - }; - - return ( - <> - - - - ); -} - -function EnvironmentCdnRoute() { - const { nameId: environmentNameId } = useEnvironment(); - const { nameId: projectNameId } = useProject(); - - return ( - - - - - - - ); -} - -const searchSchema = z.object({ - modal: z.enum(["cdn-users", "cdn-domains"]).or(z.string()).optional(), -}); - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/cdn", -)({ - validateSearch: zodValidator(searchSchema), - component: EnvironmentCdnRoute, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/index.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/index.tsx deleted file mode 100644 index bf4c1635e9..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/index.tsx +++ /dev/null @@ -1,193 +0,0 @@ -import { BackendEnvironmentDatabaseLink } from "@/domains/project/components/backend/backend-environment-database-link"; -import { useEnvironment } from "@/domains/project/data/environment-context"; -import { useProject } from "@/domains/project/data/project-context"; -import * as Layout from "@/domains/project/layouts/project-layout"; -import { - actorBuildsQueryOptions, - projectBackendQueryOptions, - projectEnvironmentQueryOptions, - projectMetadataQueryOptions, - projectVersionQueryOptions, -} from "@/domains/project/queries"; -import { GuardEnterprise } from "@/lib/guards"; -import { - Button, - Grid, - Link as RivetLink, - ValueCard, -} from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { Link, createFileRoute, redirect } from "@tanstack/react-router"; - -function environmentIdRoute() { - const { namespaceId: environmentId } = useEnvironment(); - const { gameId: projectId } = useProject(); - - const { - data: { legacyLobbiesEnabled, backendModulesEnabled }, - } = useSuspenseQuery( - projectMetadataQueryOptions({ projectId, environmentId }), - ); - - return ( - <> - - - {backendModulesEnabled ? ( - - - - ) : null} - {legacyLobbiesEnabled ? : null} - - - ); -} - -function BackendEndpointCard() { - const { namespaceId: environmentId, nameId: environmentNameId } = - useEnvironment(); - const { gameId: projectId, nameId: projectNameId } = useProject(); - - const { data } = useSuspenseQuery( - projectBackendQueryOptions({ projectId, environmentId }), - ); - - return ( - - {data.endpoint} - - } - footer={ - <> - - - Database - - - } - /> - ); -} - -function CurrentBuildCard() { - const { nameId: environmentNameId } = useEnvironment(); - const { nameId: projectNameId } = useProject(); - - const { - data: [build], - } = useSuspenseQuery( - actorBuildsQueryOptions({ - projectNameId, - environmentNameId, - tags: { current: "true" }, - }), - ); - - return ( - - - - - } - /> - ); -} - -function CurrentVersionCard() { - const { namespaceId: environmentId, nameId: environmentNameId } = - useEnvironment(); - const { gameId: projectId, nameId: projectNameId } = useProject(); - - const { - data: { namespace: environment }, - } = useSuspenseQuery( - projectEnvironmentQueryOptions({ projectId, environmentId }), - ); - const { data: version } = useSuspenseQuery( - projectVersionQueryOptions({ - projectId, - versionId: environment.versionId, - }), - ); - - return ( - - - Manage Version - - - } - /> - ); -} - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/", -)({ - beforeLoad: ({ params }) => { - throw redirect({ - to: "/projects/$projectNameId/environments/$environmentNameId/servers", - params, - }); - }, - component: environmentIdRoute, - pendingComponent: Layout.Root.Skeleton, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies.tsx deleted file mode 100644 index 481e8e4984..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { ErrorComponent } from "@/components/error-component"; -import { useEnvironment } from "@/domains/project/data/environment-context"; -import { useProject } from "@/domains/project/data/project-context"; -import * as Layout from "@/domains/project/layouts/matchmaker-layout"; -import { guardUuids } from "@/lib/guards"; -import { - type ErrorComponentProps, - Outlet, - createFileRoute, -} from "@tanstack/react-router"; - -function MatchmakerLayoutErrorComponent(props: ErrorComponentProps) { - const { nameId: environmentNameId } = useEnvironment(); - const { nameId: projectNameId } = useProject(); - - return ( - - - - ); -} - -function MatchmakerLayoutView() { - const { nameId: environmentNameId } = useEnvironment(); - const { nameId: projectNameId } = useProject(); - - return ( - - - - ); -} - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies", -)({ - component: MatchmakerLayoutView, - errorComponent: MatchmakerLayoutErrorComponent, - pendingComponent: Layout.Root.Skeleton, - beforeLoad: async ({ - location, - context: { queryClient }, - params: { projectNameId, environmentNameId }, - }) => { - await guardUuids({ - location, - queryClient, - projectNameId, - environmentNameId, - }); - }, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/index.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/index.tsx deleted file mode 100644 index aa33eae1d8..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/index.tsx +++ /dev/null @@ -1,124 +0,0 @@ -import { LobbySortSelect } from "@/domains/project/components/matchmaker/lobby-sort-select"; -import { ProjectMatchmakerListLobbyPreview } from "@/domains/project/components/matchmaker/matchmaker-list-lobby-preview"; -import { useEnvironment } from "@/domains/project/data/environment-context"; -import { useProject } from "@/domains/project/data/project-context"; -import * as Layout from "@/domains/project/layouts/matchmaker-layout"; -import { projectEnvironmentLobbiesLiveQueryOptions } from "@/domains/project/queries"; -import { - Card, - CardContent, - CardHeader, - CardTitle, - LiveBadge, -} from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { createFileRoute, useNavigate } from "@tanstack/react-router"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { useMemo } from "react"; -import { z } from "zod"; - -function MatchmakerLobbiesView() { - const { namespaceId: environmentId } = useEnvironment(); - const { gameId: projectId } = useProject(); - - const { sort, lobbyId } = Route.useSearch(); - - const navigate = useNavigate(); - const { - data: { lobbies }, - } = useSuspenseQuery( - projectEnvironmentLobbiesLiveQueryOptions({ projectId, environmentId }), - ); - - const sorted = useMemo(() => { - if (!lobbies) { - return []; - } - - if (sort === "creation-date-oldest") { - return lobbies.sort((a, b) => { - return +a.createTs - +b.createTs; - }); - } - - if (sort === "status") { - return lobbies.sort((a, b) => { - return a.readableStatus.localeCompare(b.readableStatus); - }); - } - - if (sort === "player-count-biggest") { - return lobbies.sort((a, b) => { - return b.totalPlayerCount - a.totalPlayerCount; - }); - } - - if (sort === "player-count-smallest") { - return lobbies.sort((a, b) => { - return a.totalPlayerCount - b.totalPlayerCount; - }); - } - - return lobbies.sort((a, b) => { - return +b.createTs - +a.createTs; - }); - }, [lobbies, sort]); - - return ( - - - - Lobbies - - - { - navigate({ - to: ".", - search: (prev: Record) => ({ - ...prev, - sort: value, - }), - }); - }} - /> - - - {sorted.length === 0 ? ( -
- No lobbies created. - - Run your project client & connect to start a lobby. - -
- ) : ( - - )} -
-
- ); -} - -const searchSchema = z.object({ - lobbyId: z.string().optional(), - sort: z.string().optional(), -}); - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/", -)({ - validateSearch: zodValidator(searchSchema), - staticData: { - layout: "full", - }, - component: MatchmakerLobbiesView, - pendingComponent: Layout.Content.Skeleton, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/logs.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/logs.tsx deleted file mode 100644 index 76b9e1f557..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/logs.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { ProjectMatchmakerListLobbyPreview } from "@/domains/project/components/matchmaker/matchmaker-list-lobby-preview"; -import { useEnvironment } from "@/domains/project/data/environment-context"; -import { useProject } from "@/domains/project/data/project-context"; -import * as Layout from "@/domains/project/layouts/matchmaker-layout"; -import { projectEnvironmentLogsLobbiesQueryOptions } from "@/domains/project/queries"; -import { Card, CardContent, CardHeader, CardTitle } from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { createFileRoute } from "@tanstack/react-router"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { z } from "zod"; - -function MatchmakerLogsView() { - const { namespaceId: environmentId } = useEnvironment(); - const { gameId: projectId } = useProject(); - - const search = Route.useSearch(); - - const { data: lobbies } = useSuspenseQuery( - projectEnvironmentLogsLobbiesQueryOptions({ projectId, environmentId }), - ); - - return ( - - - Logs - - - - - - ); -} - -const searchSchema = z.object({ - lobbyId: z.string().optional(), -}); - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/logs", -)({ - validateSearch: zodValidator(searchSchema), - staticData: { - layout: "full", - }, - component: MatchmakerLogsView, - pendingComponent: Layout.Content.Skeleton, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/settings.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/settings.tsx deleted file mode 100644 index 4b591bcc6e..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/settings.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { MatchMakerLobbyConfigSettingsCard } from "@/domains/project/components/matchmaker-lobby-config-settings-card"; -import { useEnvironment } from "@/domains/project/data/environment-context"; -import { useProject } from "@/domains/project/data/project-context"; -import * as Layout from "@/domains/project/layouts/matchmaker-layout"; -import { Grid } from "@rivet-gg/components"; -import { createFileRoute } from "@tanstack/react-router"; - -function MatchmakerSettingsView() { - const { namespaceId: environmentId } = useEnvironment(); - const { gameId: projectId } = useProject(); - - return ( - - - - ); -} - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/lobbies/settings", -)({ - staticData: { - layout: "full", - }, - component: MatchmakerSettingsView, - pendingComponent: Layout.Content.Skeleton, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/matchmaker.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/matchmaker.tsx deleted file mode 100644 index b80d873c41..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/matchmaker.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { createFileRoute, redirect } from "@tanstack/react-router"; - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/matchmaker", -)({ - loader: ({ params }) => { - throw redirect({ - to: "/projects/$projectNameId/environments/$environmentNameId/lobbies", - params, - }); - }, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers.tsx deleted file mode 100644 index 34e2f20e69..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { createFileRoute, redirect } from "@tanstack/react-router"; - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers", -)({ - beforeLoad: ({ params }) => { - throw redirect({ - to: "/projects/$projectNameId/environments/$environmentNameId/actors", - params, - }); - }, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers/$.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers/$.tsx deleted file mode 100644 index 9945635285..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers/$.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { createFileRoute, redirect } from "@tanstack/react-router"; - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/servers/$", -)({ - beforeLoad: ({ params, location }) => { - if (location.href.endsWith("/builds")) { - throw redirect({ - to: "/projects/$projectNameId/environments/$environmentNameId/builds", - params, - }); - } - }, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/tokens.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/tokens.tsx deleted file mode 100644 index 1cdb2edc64..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/tokens.tsx +++ /dev/null @@ -1,157 +0,0 @@ -import { useEnvironment } from "@/domains/project/data/environment-context"; -import { useProject } from "@/domains/project/data/project-context"; -import * as Layout from "@/domains/project/layouts/project-layout"; -import { projectMetadataQueryOptions } from "@/domains/project/queries"; -import { useDialog } from "@/hooks/use-dialog"; -import { - ActionCard, - Button, - CopyArea, - DocsCard, - Grid, - Text, -} from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { Link, createFileRoute } from "@tanstack/react-router"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { z } from "zod"; - -function EnvironmentTokensRoute() { - const { gameId } = useProject(); - const { namespaceId } = useEnvironment(); - - const { - data: { legacyLobbiesEnabled }, - } = useSuspenseQuery( - projectMetadataQueryOptions({ - projectId: gameId, - environmentId: namespaceId, - }), - ); - - return ( - <> - - {legacyLobbiesEnabled ? : null} - - {legacyLobbiesEnabled ? : null} - - - - ); -} - -function DevelopmentTokenCard() { - const environment = useEnvironment(); - return ( - - - Development tokens are built to let you develop your project on - your local machine with access to production APIs. - - Run the following in your terminal: - - - ); -} - -function PublicTokenCard() { - return ( - <> - - - Generate - - - } - > - - Public tokens are used from the project client. These are - safe to share with the public. - - - - ); -} - -function ServiceTokenCard() { - return ( - <> - - - Generate - - - } - > - - Service tokens are used from private API servers. These - should never be shared. - - - - ); -} - -function Modals({ publicTokenEnabled }: { publicTokenEnabled: boolean }) { - const navigate = Route.useNavigate(); - const { gameId: projectId } = useProject(); - const { namespaceId: environmentId } = useEnvironment(); - - const { modal } = Route.useSearch(); - - const GenerateEnvironmentPublicTokenDialog = - useDialog.GenerateEnvironmentPublicToken.Dialog; - const GenerateProjectEnvServiceTokenDialog = - useDialog.GenerateProjectEnvServiceToken.Dialog; - - const handleOnOpenChange = (value: boolean) => { - if (!value) { - navigate({ search: { modal: undefined } }); - } - }; - - return ( - <> - {publicTokenEnabled ? ( - - ) : null} - - - ); -} - -const searchSchema = z.object({ - modal: z.enum(["public-token", "service-token"]).or(z.string()).optional(), -}); - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/tokens", -)({ - validateSearch: zodValidator(searchSchema), - component: EnvironmentTokensRoute, - pendingComponent: Layout.Root.Skeleton, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/versions.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/versions.tsx deleted file mode 100644 index 5ae883d82c..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/versions.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { useEnvironment } from "@/domains/project/data/environment-context"; -import { useProject } from "@/domains/project/data/project-context"; -import * as Layout from "@/domains/project/layouts/project-layout"; -import { EnvironmentVersions } from "@/domains/project/views/environment-versions"; -import { createFileRoute } from "@tanstack/react-router"; - -function EnvironmentVersionsRoute() { - const { gameId: projectId, nameId: projectNameId } = useProject(); - const { namespaceId: environmentId } = useEnvironment(); - return ( - - ); -} - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/environments/$environmentNameId/versions", -)({ - component: EnvironmentVersionsRoute, - pendingComponent: Layout.Root.Skeleton, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/index.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/index.tsx deleted file mode 100644 index 1a74f58a58..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/index.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { useProject } from "@/domains/project/data/project-context"; -import * as Layout from "@/domains/project/layouts/project-layout"; -import { ProjectEnvironmentsView } from "@/domains/project/views/project-environments"; -import { createFileRoute } from "@tanstack/react-router"; - -function ProjectIdRoute() { - const { gameId: projectId, nameId: projectNameId } = useProject(); - return ( - - ); -} - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/", -)({ - component: ProjectIdRoute, - pendingComponent: Layout.Root.Skeleton, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/namespaces/$.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/namespaces/$.tsx deleted file mode 100644 index ced5955681..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/namespaces/$.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { createFileRoute, redirect } from "@tanstack/react-router"; - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/namespaces/$", -)({ - beforeLoad: ({ params, location }) => { - throw redirect({ - to: location.pathname.replace("/namespaces/", "/environments/"), - params, - }); - }, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/settings.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/settings.tsx deleted file mode 100644 index b2cd456769..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/settings.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import * as Layout from "@/domains/project/layouts/project-settings-layout"; -import { Outlet, createFileRoute } from "@tanstack/react-router"; - -function ProjectIdSettingsView() { - const { projectNameId } = Route.useParams(); - return ( - - - - ); -} - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/settings", -)({ - component: ProjectIdSettingsView, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/settings/index.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/settings/index.tsx deleted file mode 100644 index 4079a1c08a..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/settings/index.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Button, DocsCard, Grid, Text } from "@rivet-gg/components"; -import { Link, createFileRoute } from "@tanstack/react-router"; - -function CloudTokenCard() { - return ( - <> - - - Generate - - - } - > - - Cloud tokens are used to access Rivet Cloud. They are used - by the client to access Rivet Cloud. - - - - ); -} - -function ProjectTokensRoute() { - return ( - - - - ); -} - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/settings/", -)({ - component: ProjectTokensRoute, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/tokens.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/tokens.tsx deleted file mode 100644 index b9a1d30821..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/projects/$projectNameId/tokens.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { createFileRoute, redirect } from "@tanstack/react-router"; - -export const Route = createFileRoute( - "/_authenticated/_layout/projects/$projectNameId/tokens", -)({ - loader: ({ params }) => { - throw redirect({ - to: "/projects/$projectNameId/settings", - params, - }); - }, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/teams/$groupId.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/teams/$groupId.tsx deleted file mode 100644 index c1536e858e..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/teams/$groupId.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import { ErrorComponent } from "@/components/error-component"; -import { useAuth } from "@/domains/auth/contexts/auth"; -import * as Layout from "@/domains/project/layouts/group-layout"; -import { groupProjectsQueryOptions } from "@/domains/project/queries"; -import { useDialog } from "@/hooks/use-dialog"; -import { ls } from "@/lib/ls"; -import { queryClient } from "@/queries/global"; -import { - type ErrorComponentProps, - Outlet, - createFileRoute, -} from "@tanstack/react-router"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { z } from "zod"; - -export function GroupIdErrorComponent(props: ErrorComponentProps) { - return ( - - - - ); -} - -function Modals() { - const auth = useAuth(); - const navigate = Route.useNavigate(); - const { groupId } = Route.useParams(); - const { modal } = Route.useSearch(); - - const CreateGroupInviteDialog = useDialog.CreateGroupInvite.Dialog; - const CreateGroupProjectDialog = useDialog.CreateGroupProject.Dialog; - const ConfirmLeaveGroupDialog = useDialog.ConfirmLeaveGroup.Dialog; - - const handleonOpenChange = (value: boolean) => { - if (!value) { - navigate({ search: { modal: undefined } }); - } - }; - - return ( - <> - - - { - ls.recentTeam.remove(auth); - await queryClient.invalidateQueries({ refetchType: "all" }); - navigate({ to: "/" }); - }} - dialogProps={{ - open: modal === "leave", - onOpenChange: handleonOpenChange, - }} - /> - - ); -} - -function GroupIdView() { - return ( - - - - - ); -} - -const searchSchema = z.object({ - modal: z - .enum(["invite", "create-group-project", "leave"]) - .or(z.string()) - .optional(), -}); - -export const Route = createFileRoute("/_authenticated/_layout/teams/$groupId")({ - validateSearch: zodValidator(searchSchema), - component: GroupIdView, - errorComponent: GroupIdErrorComponent, - pendingComponent: Layout.Root.Skeleton, - beforeLoad: async ({ - params: { groupId }, - context: { auth, queryClient }, - }) => { - await queryClient.ensureQueryData(groupProjectsQueryOptions(groupId)); - ls.recentTeam.set(auth, groupId); - }, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/teams/$groupId/billing.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/teams/$groupId/billing.tsx deleted file mode 100644 index b9722dab72..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/teams/$groupId/billing.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { Flex, Text } from "@rivet-gg/components"; -import { createFileRoute } from "@tanstack/react-router"; - -function GroupIdBillingView() { - return ( - - Billing - - ); -} - -export const Route = createFileRoute( - "/_authenticated/_layout/teams/$groupId/billing", -)({ - component: GroupIdBillingView, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/teams/$groupId/index.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/teams/$groupId/index.tsx deleted file mode 100644 index bbb4727757..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/teams/$groupId/index.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { GroupMembers } from "@/domains/group/views/group-members"; -import { GroupProjects } from "@/domains/group/views/group-projects"; -import * as Layout from "@/domains/project/layouts/group-layout"; -import { Flex } from "@rivet-gg/components"; -import { createFileRoute } from "@tanstack/react-router"; -import { GroupIdErrorComponent } from "../$groupId"; - -function GroupIdView() { - const { groupId } = Route.useParams(); - return ( - - - - - - - - - ); -} - -export const Route = createFileRoute("/_authenticated/_layout/teams/$groupId/")( - { - component: GroupIdView, - errorComponent: GroupIdErrorComponent, - pendingComponent: Layout.Content.Skeleton, - }, -); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/teams/$groupId/members.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/teams/$groupId/members.tsx deleted file mode 100644 index 7d0b4121cf..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/teams/$groupId/members.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { GroupDetailedMembers } from "@/domains/group/views/group-detailed-members"; -import * as Layout from "@/domains/project/layouts/group-layout"; -import { Flex } from "@rivet-gg/components"; -import { createFileRoute } from "@tanstack/react-router"; - -function GroupIdMembersView() { - const { groupId } = Route.useParams(); - - return ( - - - - ); -} - -export const Route = createFileRoute( - "/_authenticated/_layout/teams/$groupId/members", -)({ - component: GroupIdMembersView, - pendingComponent: Layout.Content.Skeleton, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/teams/$groupId/settings.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/teams/$groupId/settings.tsx deleted file mode 100644 index 3ff7141045..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/teams/$groupId/settings.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import * as Layout from "@/domains/project/layouts/group-settings-layout"; -import { Outlet, createFileRoute } from "@tanstack/react-router"; - -function GroupIdSettingsView() { - const { groupId } = Route.useParams(); - return ( - - - - ); -} - -export const Route = createFileRoute( - "/_authenticated/_layout/teams/$groupId/settings", -)({ - component: GroupIdSettingsView, - pendingComponent: Layout.Root.Skeleton, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/_layout/teams/$groupId/settings/index.tsx b/frontend/apps/hub/src/routes/_authenticated/_layout/teams/$groupId/settings/index.tsx deleted file mode 100644 index e7124149de..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/_layout/teams/$groupId/settings/index.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { GroupImageSettingsCard } from "@/domains/group/components/group-image-settings-card"; -import { GroupNameSettingsCard } from "@/domains/group/components/group-name-settings-card"; -import { Flex } from "@rivet-gg/components"; -import { createFileRoute } from "@tanstack/react-router"; - -function GroupIdSettingsView() { - const { groupId } = Route.useParams(); - return ( - - - - - ); -} - -export const Route = createFileRoute( - "/_authenticated/_layout/teams/$groupId/settings/", -)({ - component: GroupIdSettingsView, - pendingComponent: () => { - return ( - - - - - ); - }, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/billing.tsx b/frontend/apps/hub/src/routes/_authenticated/billing.tsx deleted file mode 100644 index d2a09dd810..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/billing.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { ProjectSelect } from "@/domains/project/components/project-select"; -import { projectQueryOptions } from "@/domains/project/queries"; -import * as Layout from "@/layouts/page-centered"; -import { guardEnterprise } from "@/lib/guards"; -import { - Button, - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, -} from "@rivet-gg/components"; -import { useQuery } from "@tanstack/react-query"; -import { Link, createFileRoute } from "@tanstack/react-router"; -import { useState } from "react"; - -function BillingRoute() { - const [projectId, setProjectId] = useState(null); - - const { data, isLoading } = useQuery({ - // biome-ignore lint/style/noNonNullAssertion: it's safe to assume that projectId exists - ...projectQueryOptions(projectId!), - enabled: !!projectId, - }); - - return ( - - - - Billing - - Choose a project for which you would like to manage - billing. - - - - - - - - - - - ); -} - -export const Route = createFileRoute("/_authenticated/billing")({ - beforeLoad: async ({ context: { queryClient } }) => { - await guardEnterprise({ queryClient }); - }, - component: BillingRoute, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/devices.link.tsx b/frontend/apps/hub/src/routes/_authenticated/devices.link.tsx deleted file mode 100644 index 81f10da8f9..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/devices.link.tsx +++ /dev/null @@ -1,156 +0,0 @@ -import { Onboarding } from "@/components/onboarding/onboarding"; -import * as DeviceLinkForm from "@/domains/auth/forms/device-link-form"; -import { - deviceLinkTokenQueryOptions, - useCompleteDeviceLinkMutation, -} from "@/domains/auth/queries"; -import { projectsByGroupQueryOptions } from "@/domains/project/queries"; -import { queryClient } from "@/queries/global"; -import { - Button, - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, - Flex, - Page, - Text, -} from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { Link, createFileRoute, notFound } from "@tanstack/react-router"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { z } from "zod"; - -function DeviceLinkTokenRoute() { - const navigate = Route.useNavigate(); - const { token, newbie } = Route.useSearch(); - - const { mutateAsync, isSuccess, variables } = - useCompleteDeviceLinkMutation(); - const { data: groups, refetch } = useSuspenseQuery( - projectsByGroupQueryOptions(), - ); - - if (groups.length === 0 || newbie) { - return ( - { - await refetch(); - if (newbie) { - navigate({ - to: ".", - search: (prev) => ({ ...prev, newbie: undefined }), - }); - } - }} - /> - ); - } - - if (isSuccess) { - return ( - - - - Project Linked Successfully - - - - You may safely close this tab and return to your - project. - - - - - - - - ); - } - - return ( - { - await mutateAsync({ - deviceLinkToken: token, - gameId: values.projectId, - }); - }} - defaultValues={{ - token, - projectId: - groups.length === 1 && groups[0].projects.length === 1 - ? groups[0].projects[0].gameId - : "", - }} - > - - - - Link project - - Link your project to your device here to continue - with Rivet setup. - - - - - - - - - - Continue - - - - - - - ); -} - -export const searchSchema = z.object({ - token: z.string(), - newbie: z.boolean().optional(), -}); - -export const Route = createFileRoute("/_authenticated/devices/link")({ - validateSearch: zodValidator(searchSchema), - component: DeviceLinkTokenRoute, - staticData: { - layout: "onboarding", - }, - beforeLoad: async ({ search: { token } }) => { - try { - const response = await queryClient.fetchQuery( - deviceLinkTokenQueryOptions(token), - ); - if (!response) { - throw notFound(); - } - } catch { - throw notFound(); - } - }, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/devices.link_.$token.tsx b/frontend/apps/hub/src/routes/_authenticated/devices.link_.$token.tsx deleted file mode 100644 index e116ad7326..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/devices.link_.$token.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { createFileRoute, redirect } from "@tanstack/react-router"; - -export const Route = createFileRoute("/_authenticated/devices/link_/$token")({ - beforeLoad: async ({ params: { token } }) => { - throw redirect({ - to: "/devices/link", - search: { token }, - }); - }, -}); diff --git a/frontend/apps/hub/src/routes/_authenticated/invite.$inviteCode.tsx b/frontend/apps/hub/src/routes/_authenticated/invite.$inviteCode.tsx deleted file mode 100644 index d3163fec75..0000000000 --- a/frontend/apps/hub/src/routes/_authenticated/invite.$inviteCode.tsx +++ /dev/null @@ -1,126 +0,0 @@ -import { GroupAvatar } from "@/domains/group/components/group-avatar"; -import { - groupInviteQueryOptions, - useGroupInviteAcceptMutation, -} from "@/domains/group/queries"; -import * as Layout from "@/layouts/page-centered"; -import { isRivetError } from "@/lib/utils"; -import { queryClient } from "@/queries/global"; -import { - Button, - Card, - CardDescription, - CardFooter, - CardHeader, - CardTitle, - Flex, - Strong, -} from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { Link, createFileRoute, notFound } from "@tanstack/react-router"; - -const TranslatedError = ({ error }: { error: Error }) => { - if (isRivetError(error)) { - if (error.body.code === "GROUP_ALREADY_MEMBER") { - return <>You're already a member of this group.; - } - if (error.body.code === "GROUP_INVITE_CODE_ALREADY_USED") { - return <>This invite code has already been used.; - } - } - - return <>An error occurred. Please try again later.; -}; - -function InviteCodeInviteRoute() { - const { inviteCode } = Route.useParams(); - - const { data } = useSuspenseQuery(groupInviteQueryOptions(inviteCode)); - const { mutate, isPending, isError, error } = - useGroupInviteAcceptMutation(); - - if (isError) { - return ( - - - - - - Invitation from - - - {data.group.displayName} - - - - - - - - - - - - - - - ); - } - - return ( - - - - - - Invitation from - - - {data.group.displayName} - - - - - You've been invited to join the team{" "} - {data.group.displayName}. Do you want - to accept the invitation? - - - - - - - - - - - ); -} - -export const Route = createFileRoute("/_authenticated/invite/$inviteCode")({ - component: InviteCodeInviteRoute, - loader: async ({ params: { inviteCode } }) => { - const invite = await queryClient.fetchQuery( - groupInviteQueryOptions(inviteCode), - ); - - if (!invite) { - throw notFound(); - } - }, -}); diff --git a/frontend/apps/hub/src/vite-env.d.ts b/frontend/apps/hub/src/vite-env.d.ts deleted file mode 100644 index 3155e77625..0000000000 --- a/frontend/apps/hub/src/vite-env.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -/// - -declare const __APP_BUILD_ID__: string; - -declare module "vite-plugin-favicons-inject" { - import type { Plugin } from "vite"; - - export default function vitePluginFaviconsInject( - iconPath: string, - // biome-ignore lint/suspicious/noExplicitAny: - options: Record, - ): Plugin; -} - -declare module "*?shiki&lang=bash" { - const src: string; - export default src; - export const source: string; -} diff --git a/frontend/apps/hub/tailwind.config.js b/frontend/apps/hub/tailwind.config.js deleted file mode 100644 index ba962d04fd..0000000000 --- a/frontend/apps/hub/tailwind.config.js +++ /dev/null @@ -1,16 +0,0 @@ -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: [ - "./src/**/components/**/*.{ts,tsx}", - "./src/layouts/**/*.{ts,tsx}", - "./src/forms/**/*.{ts,tsx}", - "./src/lib/**/*.{ts,tsx}", - "./src/**/hooks/**/*.{ts,tsx}", - "./src/**/forms/**/*.{ts,tsx}", - "./src/**/layouts/**/*.{ts,tsx}", - "./src/**/views/**/*.{ts,tsx}", - "./src/**/routes/**/*.{ts,tsx}", - "../../../node_modules/@rivet-gg/components/src/**/*.{ts,tsx}", - ], - presets: [require("@rivet-gg/components/tailwind-base")], -}; diff --git a/frontend/apps/hub/tsconfig.json b/frontend/apps/hub/tsconfig.json deleted file mode 100644 index 2638acb5ff..0000000000 --- a/frontend/apps/hub/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "composite": true, - "compilerOptions": { - "skipLibCheck": true, - "target": "ESNext", - "strict": true, - "esModuleInterop": true, - "noEmit": true, - "moduleResolution": "bundler", - "module": "Preserve", - "jsx": "react-jsx", - "baseUrl": ".", - "paths": { - "@/*": ["./src/*"] - } - }, - "include": ["src", "vite.config.ts"] -} diff --git a/frontend/apps/hub/turbo.json b/frontend/apps/hub/turbo.json deleted file mode 100644 index 04f194325f..0000000000 --- a/frontend/apps/hub/turbo.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "extends": ["//"], - "tasks": { - "build": { - "env": ["VITE_APP_*"], - "outputs": ["dist/**"] - }, - "build:embedded": { - "env": ["VITE_APP_*"], - "outputs": ["dist/**"] - }, - "dev": { - "env": ["VITE_APP_*"], - "persistent": true - } - } -} diff --git a/frontend/apps/hub/vendor/rivet-gg-api-ee.tgz b/frontend/apps/hub/vendor/rivet-gg-api-ee.tgz deleted file mode 100644 index 6b85b31c4f..0000000000 --- a/frontend/apps/hub/vendor/rivet-gg-api-ee.tgz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b75e933e7eaa1f28750875eed12a4e425a59e7cf0771d6f70c4bd7e9d1b8a525 -size 577685 diff --git a/frontend/apps/hub/vite.config.ts b/frontend/apps/hub/vite.config.ts deleted file mode 100644 index c7e92a7bf8..0000000000 --- a/frontend/apps/hub/vite.config.ts +++ /dev/null @@ -1,75 +0,0 @@ -import * as crypto from "node:crypto"; -import path from "node:path"; -import mdx from "@mdx-js/rollup"; -import { sentryVitePlugin } from "@sentry/vite-plugin"; -import { TanStackRouterVite } from "@tanstack/router-plugin/vite"; -import react from "@vitejs/plugin-react"; -import { visualizer } from "rollup-plugin-visualizer"; -import { defineConfig } from "vite"; -import vitePluginFaviconsInject from "vite-plugin-favicons-inject"; - -// These are only needed in CI. They'll be undefined in dev. -const GIT_BRANCH = process.env.CF_PAGES_BRANCH; -const GIT_SHA = process.env.CF_PAGES_COMMIT_SHA; - -// https://vitejs.dev/config/ -export default defineConfig({ - base: "./", - plugins: [ - react(), - TanStackRouterVite(), - vitePluginFaviconsInject( - path.resolve(__dirname, "public", "icon-white.svg"), - { - appName: "Rivet Hub", - theme_color: "#ff4f00", - }, - ), - process.env.SENTRY_AUTH_TOKEN - ? sentryVitePlugin({ - org: "rivet-gaming", - project: "hub", - authToken: process.env.SENTRY_AUTH_TOKEN, - release: - GIT_BRANCH === "main" ? { name: GIT_SHA } : undefined, - }) - : null, - process.env.DEBUG_BUNDLE ? visualizer() : null, - ], - server: { - host: "0.0.0.0", - port: 5080, - allowedHosts: true, - // Listen on a different port since we don't proxy WebSockets on /ui - hmr: { - port: 5080, - host: "127.0.0.1", - }, - }, - preview: { - port: 5080, - }, - define: { - // Provide a unique build ID for cache busting - __APP_BUILD_ID__: JSON.stringify( - `${new Date().toISOString()}@${crypto.randomUUID()}`, - ), - }, - resolve: { - alias: { - "@": path.resolve(__dirname, "./src"), - }, - }, - build: { - sourcemap: true, - commonjsOptions: { - include: [/@rivet-gg\/components/, /node_modules/], - }, - }, - optimizeDeps: { - include: ["@fortawesome/*", "@rivet-gg/icons"], - }, - worker: { - format: "es", - }, -}); diff --git a/frontend/apps/studio/.env b/frontend/apps/studio/.env deleted file mode 100644 index 313e1ba527..0000000000 --- a/frontend/apps/studio/.env +++ /dev/null @@ -1,12 +0,0 @@ -VITE_APP_API_URL=http://127.0.0.1:8080 -VITE_APP_ASSETS_URL=https://assets2.rivet.gg -VITE_APP_SENTRY_DSN="https://66a566505cfb4341732a3d350f2b87e2@o4504307129188352.ingest.sentry.io/4506435887366144" -VITE_APP_SENTRY_PROJECT_ID="4506435887366144" -# This is a public-facing token, safe to commit to repo -VITE_APP_POSTHOG_API_KEY=phc_6kfTNEAVw7rn1LA51cO3D69FefbKupSWFaM7OUgEpEo -VITE_APP_POSTHOG_HOST=https://ph.rivet.gg - -# Overridden in CI -VITE_APP_OUTERBASE_PROVIDER_TOKEN= -SENTRY_AUTH_TOKEN= - diff --git a/frontend/apps/studio/README.md b/frontend/apps/studio/README.md deleted file mode 100644 index 7c80276f58..0000000000 --- a/frontend/apps/studio/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Rivet's Actor Core Studio - -[studio.actorcore.org](https://studio.actorcore.org) - -## Developing - -```bash -cd frontend/apps/actor-core-studio -yarn install -yarn dlx turbo dev -``` - -Open [http://localhost:43708](http://localhost:43708) in your browser to view the website. - -## Configuring - -Create a file called `.env.local` to override properties. - -## License - -This site template is a commercial product and is licensed under the [Tailwind UI license](https://tailwindui.com/license). - diff --git a/frontend/apps/studio/index.html b/frontend/apps/studio/index.html deleted file mode 100644 index 10a2ef0382..0000000000 --- a/frontend/apps/studio/index.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - Rivet ⋅ Studio - - -
- - - - - diff --git a/frontend/apps/studio/package.json b/frontend/apps/studio/package.json deleted file mode 100644 index 4a9698a70a..0000000000 --- a/frontend/apps/studio/package.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "name": "@rivet-gg/studio", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "ts-check": "tsc --noEmit", - "build": "vite build --mode=production --base=/", - "preview": "vite preview" - }, - "dependencies": { - "@date-fns/utc": "^1.2.0", - "@fortawesome/fontawesome-svg-core": "^6.5.2", - "@fortawesome/free-brands-svg-icons": "^6.5.2", - "@fortawesome/free-solid-svg-icons": "^6.5.2", - "@fortawesome/react-fontawesome": "^0.2.2", - "@hookform/resolvers": "^3.3.4", - "@rivet-gg/components": "workspace:*", - "@rivet-gg/icons": "workspace:*", - "@sentry/react": "^8.26.0", - "@sentry/vite-plugin": "^2.22.2", - "@tanstack/react-router": "^1.114.25", - "@tanstack/react-table": "^8.20.6", - "@tanstack/router-devtools": "^1.114.25", - "@tanstack/router-plugin": "^1.114.25", - "@tanstack/zod-adapter": "^1.114.25", - "@types/bcryptjs": "^2.4.6", - "@types/file-saver": "^2", - "@types/filesize": "^5.0.2", - "@types/lodash": "^4.17.14", - "@types/mdx": "^2.0.13", - "@types/mime": "^4.0.0", - "@types/node": "^20.11.30", - "@types/react": "^18.2.66", - "@types/react-dom": "^18.2.22", - "@vitejs/plugin-react": "^4.2.1", - "actor-core": "^0.6.2", - "autoprefixer": "^10.4.19", - "bcryptjs": "^2.4.3", - "file-saver": "^2.0.5", - "framer-motion": "^11.2.11", - "jotai": "^2.12.2", - "jotai-devtools": "^0.11.0", - "jotai-effect": "^2.0.2", - "postcss": "^8.4.38", - "posthog-js": "^1.144.2", - "react": "^19.0.0", - "react-dom": "^19.0.0", - "tailwind-merge": "^2.2.2", - "tailwindcss": "^3.4.1", - "tailwindcss-animate": "^1.0.7", - "typescript": "^5.5.4", - "usehooks-ts": "^3.1.0", - "vite": "^5.2.0", - "vite-plugin-favicons-inject": "^2.2.0", - "zod": "^3.24" - } -} diff --git a/frontend/apps/studio/postcss.config.js b/frontend/apps/studio/postcss.config.js deleted file mode 100644 index 7b75c83aff..0000000000 --- a/frontend/apps/studio/postcss.config.js +++ /dev/null @@ -1,6 +0,0 @@ -export default { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -}; diff --git a/frontend/apps/studio/public/logo.svg b/frontend/apps/studio/public/logo.svg deleted file mode 100644 index 9086ec836c..0000000000 --- a/frontend/apps/studio/public/logo.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/apps/studio/src/app.tsx b/frontend/apps/studio/src/app.tsx deleted file mode 100644 index 29c6f48791..0000000000 --- a/frontend/apps/studio/src/app.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { - ConfigProvider, - FullscreenLoading, - ThirdPartyProviders, - Toaster, - TooltipProvider, - getConfig, -} from "@rivet-gg/components"; -import { - actorFiltersAtom, - currentActorIdAtom, - pickActorListFilters, -} from "@rivet-gg/components/actors"; -import { PageLayout } from "@rivet-gg/components/layout"; -import * as Sentry from "@sentry/react"; -import { RouterProvider, createRouter } from "@tanstack/react-router"; -import { useAtom } from "jotai"; -import { withAtomEffect } from "jotai-effect"; -import { Suspense } from "react"; -import { routeTree } from "./routeTree.gen"; - -declare module "@tanstack/react-router" { - interface Register { - router: typeof router; - } -} - -export const router = createRouter({ - basepath: import.meta.env.BASE_URL, - routeTree, - defaultStaleTime: Number.POSITIVE_INFINITY, - defaultPendingComponent: PageLayout.Root.Skeleton, - defaultPreloadStaleTime: 0, - defaultOnCatch: (error) => { - Sentry.captureException(error); - }, -}); - -const effect = withAtomEffect(actorFiltersAtom, (get, set) => { - // set initial values - const search = router.state.location.search; - - const filters = pickActorListFilters(search); - - set(actorFiltersAtom, filters); - set(currentActorIdAtom, router.state.location.search.actorId); -}); - -const effect2 = withAtomEffect(actorFiltersAtom, (get, set) => { - return router.subscribe("onResolved", (event) => { - set(actorFiltersAtom, pickActorListFilters(event.toLocation.search)); - set(currentActorIdAtom, event.toLocation.search.actorId); - }); -}); - -function InnerApp() { - useAtom(effect); - useAtom(effect2); - - return ; -} - -export function App() { - return ( - - - }> - - - - - - - - - ); -} diff --git a/frontend/apps/studio/src/components/actors.tsx b/frontend/apps/studio/src/components/actors.tsx deleted file mode 100644 index 6a4c57a7a7..0000000000 --- a/frontend/apps/studio/src/components/actors.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { - ActorFeature, - ActorsActorDetails, - ActorsActorEmptyDetails, - ActorsListPreview, - currentActorAtom, -} from "@rivet-gg/components/actors"; -import { useNavigate, useSearch } from "@tanstack/react-router"; -import { useAtomValue } from "jotai"; - -export function Actors({ actorId }: { actorId: string | undefined }) { - return ( - - {actorId ? ( - - ) : ( - - )} - - ); -} - -function Actor() { - const actor = useAtomValue(currentActorAtom); - const navigate = useNavigate(); - const { tab } = useSearch({ from: "/_layout/" }); - - if (!actor) { - return null; - } - return ( - { - navigate({ - to: ".", - search: (old) => ({ ...old, tab }), - }); - }} - /> - ); -} diff --git a/frontend/apps/studio/src/components/layout.tsx b/frontend/apps/studio/src/components/layout.tsx deleted file mode 100644 index 8fbf3fe559..0000000000 --- a/frontend/apps/studio/src/components/layout.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { connectionStateAtom } from "@/stores/manager"; -import { DocsSheet, ShimmerLine, cn } from "@rivet-gg/components"; -import { NavItem, Header as RivetHeader } from "@rivet-gg/components/header"; -import { Icon, faGithub } from "@rivet-gg/icons"; -import { Link } from "@tanstack/react-router"; -import { useAtomValue } from "jotai"; -import type { PropsWithChildren, ReactNode } from "react"; - -interface RootProps { - children: ReactNode; -} - -const Root = ({ children }: RootProps) => { - return
{children}
; -}; - -const Main = ({ children }: RootProps) => { - return ( -
- {children} -
- ); -}; - -const VisibleInFull = ({ children }: PropsWithChildren) => { - return ( -
- {children} -
- ); -}; - -const Header = () => { - const connectionStatus = useAtomValue(connectionStateAtom); - return ( - } - addons={ - connectionStatus !== "connected" ? ( - - ) : null - } - links={ - <> - - - - - - - - Documentation - - - - ({ ...old, modal: "feedback" })} - > - Feedback - - - - } - /> - ); -}; - -const Footer = () => { - return null; -}; - -export { Root, Main, Header, Footer, VisibleInFull }; diff --git a/frontend/apps/studio/src/content/dev-bun.sh b/frontend/apps/studio/src/content/dev-bun.sh deleted file mode 100644 index 5316766445..0000000000 --- a/frontend/apps/studio/src/content/dev-bun.sh +++ /dev/null @@ -1 +0,0 @@ -bunx @actor-core/cli@latest dev \ No newline at end of file diff --git a/frontend/apps/studio/src/content/dev-npm.sh b/frontend/apps/studio/src/content/dev-npm.sh deleted file mode 100644 index 6f2a7e03ee..0000000000 --- a/frontend/apps/studio/src/content/dev-npm.sh +++ /dev/null @@ -1 +0,0 @@ -npx @actor-core/cli@latest dev \ No newline at end of file diff --git a/frontend/apps/studio/src/content/dev-pnpm.sh b/frontend/apps/studio/src/content/dev-pnpm.sh deleted file mode 100644 index 2f24a9bce7..0000000000 --- a/frontend/apps/studio/src/content/dev-pnpm.sh +++ /dev/null @@ -1 +0,0 @@ -pnpx @actor-core/cli@latest dev \ No newline at end of file diff --git a/frontend/apps/studio/src/content/dev-yarn.sh b/frontend/apps/studio/src/content/dev-yarn.sh deleted file mode 100644 index fac5662313..0000000000 --- a/frontend/apps/studio/src/content/dev-yarn.sh +++ /dev/null @@ -1 +0,0 @@ -yarn dlx @actor-core/cli@latest dev \ No newline at end of file diff --git a/frontend/apps/studio/src/index.css b/frontend/apps/studio/src/index.css deleted file mode 100644 index 61131ed697..0000000000 --- a/frontend/apps/studio/src/index.css +++ /dev/null @@ -1,54 +0,0 @@ -@import "@rivet-gg/components/theme.css"; - -@tailwind base; -@tailwind components; -@tailwind utilities; - -@layer base { - * { - @apply border-border; - } - body { - @apply bg-background text-foreground min-h-screen; - } - #root { - @apply min-h-screen; - } -} - -@layer utilities { - .overflow-r-gradient { - mask-image: linear-gradient(-90deg, rgba(0, 0, 0, 0) 0%, #000 45px); - } - - .step { - counter-increment: step; - } - - .step:before { - @apply absolute inline-flex h-9 w-9 items-center justify-center rounded-full border-4 border-background bg-primary text-center -indent-px font-mono text-base font-medium; - @apply ml-[-50px] mt-[-4px]; - content: counter(step); - } -} - -:root { - /* biome-ignore lint/correctness/noUnknownFunction: tailwind functions */ - --shiki-color-text: theme("colors.white"); - /* biome-ignore lint/correctness/noUnknownFunction: tailwind functions */ - --shiki-token-constant: theme("colors.violet.300"); - /* biome-ignore lint/correctness/noUnknownFunction: tailwind functions */ - --shiki-token-string: theme("colors.violet.300"); - /* biome-ignore lint/correctness/noUnknownFunction: tailwind functions */ - --shiki-token-comment: theme("colors.zinc.500"); - /* biome-ignore lint/correctness/noUnknownFunction: tailwind functions */ - --shiki-token-keyword: theme("colors.sky.300"); - /* biome-ignore lint/correctness/noUnknownFunction: tailwind functions */ - --shiki-token-parameter: theme("colors.pink.300"); - /* biome-ignore lint/correctness/noUnknownFunction: tailwind functions */ - --shiki-token-function: theme("colors.violet.300"); - /* biome-ignore lint/correctness/noUnknownFunction: tailwind functions */ - --shiki-token-string-expression: theme("colors.violet.300"); - /* biome-ignore lint/correctness/noUnknownFunction: tailwind functions */ - --shiki-token-punctuation: theme("colors.zinc.200"); -} diff --git a/frontend/apps/studio/src/main.tsx b/frontend/apps/studio/src/main.tsx deleted file mode 100644 index 1ea05786cb..0000000000 --- a/frontend/apps/studio/src/main.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { StrictMode } from "react"; -import ReactDOM from "react-dom/client"; -import { App, router } from "./app"; -import "./index.css"; -import { initThirdPartyProviders } from "@rivet-gg/components"; - -initThirdPartyProviders(router, import.meta.env.DEV); - -// biome-ignore lint/style/noNonNullAssertion: it should always be present -const rootElement = document.getElementById("root")!; -if (!rootElement.innerHTML) { - const root = ReactDOM.createRoot(rootElement); - root.render( - - - , - ); -} diff --git a/frontend/apps/studio/src/queries/global.ts b/frontend/apps/studio/src/queries/global.ts deleted file mode 100644 index 96ea5f93d5..0000000000 --- a/frontend/apps/studio/src/queries/global.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { toast } from "@rivet-gg/components"; -import { broadcastQueryClient } from "@tanstack/query-broadcast-client-experimental"; -import { createSyncStoragePersister } from "@tanstack/query-sync-storage-persister"; -import { MutationCache, QueryCache, QueryClient } from "@tanstack/react-query"; -import superjson from "superjson"; - -const queryCache = new QueryCache(); - -const mutationCache = new MutationCache({ - onError(error, variables, context, mutation) { - if (mutation.meta?.hideErrorToast) { - return; - } - toast.error("Error occurred while performing the operation.", { - description: error.message, - }); - }, -}); - -export const queryClient = new QueryClient({ - defaultOptions: { - queries: { - staleTime: 5 * 1000, - gcTime: 1000 * 60 * 60 * 24, - retry: 2, - refetchOnWindowFocus: false, - refetchOnReconnect: false, - }, - }, - queryCache, - mutationCache, -}); - -export const queryClientPersister = createSyncStoragePersister({ - storage: window.localStorage, - serialize: superjson.stringify, - deserialize: superjson.parse, -}); - -broadcastQueryClient({ - queryClient, - broadcastChannel: "rivet-gg-hub", -}); diff --git a/frontend/apps/studio/src/routeTree.gen.ts b/frontend/apps/studio/src/routeTree.gen.ts deleted file mode 100644 index 51c6349f4a..0000000000 --- a/frontend/apps/studio/src/routeTree.gen.ts +++ /dev/null @@ -1,121 +0,0 @@ -/* eslint-disable */ - -// @ts-nocheck - -// noinspection JSUnusedGlobalSymbols - -// This file was automatically generated by TanStack Router. -// You should NOT make any changes in this file as it will be overwritten. -// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. - -// Import Routes - -import { Route as rootRoute } from './routes/__root' -import { Route as LayoutImport } from './routes/_layout' -import { Route as LayoutIndexImport } from './routes/_layout/index' - -// Create/Update Routes - -const LayoutRoute = LayoutImport.update({ - id: '/_layout', - getParentRoute: () => rootRoute, -} as any) - -const LayoutIndexRoute = LayoutIndexImport.update({ - id: '/', - path: '/', - getParentRoute: () => LayoutRoute, -} as any) - -// Populate the FileRoutesByPath interface - -declare module '@tanstack/react-router' { - interface FileRoutesByPath { - '/_layout': { - id: '/_layout' - path: '' - fullPath: '' - preLoaderRoute: typeof LayoutImport - parentRoute: typeof rootRoute - } - '/_layout/': { - id: '/_layout/' - path: '/' - fullPath: '/' - preLoaderRoute: typeof LayoutIndexImport - parentRoute: typeof LayoutImport - } - } -} - -// Create and export the route tree - -interface LayoutRouteChildren { - LayoutIndexRoute: typeof LayoutIndexRoute -} - -const LayoutRouteChildren: LayoutRouteChildren = { - LayoutIndexRoute: LayoutIndexRoute, -} - -const LayoutRouteWithChildren = - LayoutRoute._addFileChildren(LayoutRouteChildren) - -export interface FileRoutesByFullPath { - '': typeof LayoutRouteWithChildren - '/': typeof LayoutIndexRoute -} - -export interface FileRoutesByTo { - '/': typeof LayoutIndexRoute -} - -export interface FileRoutesById { - __root__: typeof rootRoute - '/_layout': typeof LayoutRouteWithChildren - '/_layout/': typeof LayoutIndexRoute -} - -export interface FileRouteTypes { - fileRoutesByFullPath: FileRoutesByFullPath - fullPaths: '' | '/' - fileRoutesByTo: FileRoutesByTo - to: '/' - id: '__root__' | '/_layout' | '/_layout/' - fileRoutesById: FileRoutesById -} - -export interface RootRouteChildren { - LayoutRoute: typeof LayoutRouteWithChildren -} - -const rootRouteChildren: RootRouteChildren = { - LayoutRoute: LayoutRouteWithChildren, -} - -export const routeTree = rootRoute - ._addFileChildren(rootRouteChildren) - ._addFileTypes() - -/* ROUTE_MANIFEST_START -{ - "routes": { - "__root__": { - "filePath": "__root.tsx", - "children": [ - "/_layout" - ] - }, - "/_layout": { - "filePath": "_layout.tsx", - "children": [ - "/_layout/" - ] - }, - "/_layout/": { - "filePath": "_layout/index.tsx", - "parent": "/_layout" - } - } -} -ROUTE_MANIFEST_END */ diff --git a/frontend/apps/studio/src/routes/__root.tsx b/frontend/apps/studio/src/routes/__root.tsx deleted file mode 100644 index 8e36fa8ba6..0000000000 --- a/frontend/apps/studio/src/routes/__root.tsx +++ /dev/null @@ -1,132 +0,0 @@ -import { FEEDBACK_FORM_ID, FullscreenLoading } from "@rivet-gg/components"; - -import * as Layout from "@/components/layout"; -import { useDialog } from "@rivet-gg/components/actors"; -import { Outlet, createRootRouteWithContext } from "@tanstack/react-router"; -import { TanStackRouterDevtools } from "@tanstack/react-router-devtools"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { usePostHog } from "posthog-js/react"; -import { Suspense } from "react"; -import { z } from "zod"; - -function Modals() { - const search = Route.useSearch(); - const navigate = Route.useNavigate(); - - const posthog = usePostHog(); - - const FeedbackDialog = useDialog.Feedback.Dialog; - const GoToActorDialog = useDialog.GoToActor.Dialog; - const CreateActorDialog = useDialog.CreateActor.Dialog; - - const { modal, utm_source } = search; - - const handleOnOpenChange = (value: boolean) => { - if (!value) { - navigate({ search: (old) => ({ ...old, modal: undefined }) }); - } else { - posthog.capture("survey shown", { $survey_id: FEEDBACK_FORM_ID }); - } - }; - - return ( - <> - - { - navigate({ - to: ".", - search: (old) => ({ - ...old, - actorId, - modal: undefined, - }), - }); - }} - dialogProps={{ - open: modal === "go-to-actor", - onOpenChange: (value) => { - if (!value) { - navigate({ search: { modal: undefined } }); - } - }, - }} - /> - { - if (!value) { - navigate({ search: { modal: undefined } }); - } - }, - }} - /> - - ); -} - -// function RootNotFoundComponent() { -// return ( -// -// -// -// -// -// ); -// } - -// function RootErrorComponent(props: ErrorComponentProps) { -// return ( -// -// -// -// -// -// ); -// } - -function Root() { - return ( - - - - - {/* */} - - - - - - ); -} - -function RootRoute() { - return ( - <> - - - - - {import.meta.env.DEV ? : null} - - ); -} - -const searchSchema = z.object({ - modal: z.enum(["go-to-actor", "feedback"]).or(z.string()).optional(), - utm_source: z.string().optional(), -}); - -export const Route = createRootRouteWithContext()({ - validateSearch: zodValidator(searchSchema), - component: RootRoute, - pendingComponent: FullscreenLoading, - wrapInSuspense: true, -}); diff --git a/frontend/apps/studio/src/routes/_layout.tsx b/frontend/apps/studio/src/routes/_layout.tsx deleted file mode 100644 index d40b51ba1e..0000000000 --- a/frontend/apps/studio/src/routes/_layout.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { Outlet, createFileRoute } from "@tanstack/react-router"; - -export const Route = createFileRoute("/_layout")({ - component: RouteComponent, -}); - -function RouteComponent() { - return ( -
- -
- ); -} diff --git a/frontend/apps/studio/src/routes/_layout/index.tsx b/frontend/apps/studio/src/routes/_layout/index.tsx deleted file mode 100644 index d606a91a8a..0000000000 --- a/frontend/apps/studio/src/routes/_layout/index.tsx +++ /dev/null @@ -1,222 +0,0 @@ -import { Actors } from "@/components/actors"; -import { - connectionEffect, - connectionStateAtom, - initiallyConnectedAtom, -} from "@/stores/manager"; -import { - Button, - Card, - CardContent, - CardFooter, - CardHeader, - CardTitle, - CodeFrame, - CodeGroup, - CodeSource, - DocsSheet, - H1, - Link, - Strong, -} from "@rivet-gg/components"; -import { - ActorsListFiltersSchema, - currentActorIdAtom, -} from "@rivet-gg/components/actors"; -import { - Icon, - faBrave, - faChrome, - faReact, - faSafari, - faTs, -} from "@rivet-gg/icons"; -import { createFileRoute } from "@tanstack/react-router"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { AnimatePresence, motion } from "framer-motion"; -import { useAtom, useAtomValue, useSetAtom } from "jotai"; -import { useEffect } from "react"; -import { z } from "zod"; -// @ts-expect-error types are missing -import devNpm, { source as devNpmSource } from "../../content/dev-npm.sh?shiki"; -import devPnpm, { - source as devPnpmSource, - // @ts-expect-error types are missing -} from "../../content/dev-pnpm.sh?shiki"; -import devYarn, { - source as devYarnSource, - // @ts-expect-error types are missing -} from "../../content/dev-yarn.sh?shiki"; - -import devBun, { - source as devBunSource, - // @ts-expect-error types are missing -} from "../../content/dev-bun.sh?shiki"; - -export const Route = createFileRoute("/_layout/")({ - component: RouteComponent, - validateSearch: zodValidator( - z - .object({ - actorId: z.string().optional(), - tab: z.string().optional(), - }) - .merge(ActorsListFiltersSchema), - ), -}); - -function RouteComponent() { - useAtom(connectionEffect); - - const isInitiallyConnected = useAtomValue(initiallyConnectedAtom); - const status = useAtomValue(connectionStateAtom); - - const { actorId } = Route.useSearch(); - - const setCurrentActorId = useSetAtom(currentActorIdAtom); - - useEffect(() => { - setCurrentActorId(actorId); - }, [actorId, setCurrentActorId]); - - return ( - - {status === "disconnected" && !isInitiallyConnected ? ( - -

Rivet Studio

- - - Getting Started - - -

- Get started with one of our quick start guides: -

-
-
- - - - - - -
-
-
-
- - - Connect to Project - - -

- Connect Rivet Studio to your ActorCore project, - using the following command: -

- - - - {devNpm} - - - {devPnpm} - - - {devBun} - - - {devYarn} - - -
-
- - - - Having trouble connecting? - - -

- Rivet Studio works best in{" "} - - Chrome - - . Some browsers like{" "} - - Safari - {" "} - and{" "} - - Brave - {" "} - block access to localhost by default. -

-
- -

- Having issues? Join the{" "} - - Rivet Discord - {" "} - or{" "} - - file a GitHub Issue - - . -

-
-
-
- ) : ( - - )} -
- ); -} diff --git a/frontend/apps/studio/src/stores/manager.tsx b/frontend/apps/studio/src/stores/manager.tsx deleted file mode 100644 index 1a5d863b64..0000000000 --- a/frontend/apps/studio/src/stores/manager.tsx +++ /dev/null @@ -1,207 +0,0 @@ -import { toast } from "@rivet-gg/components"; -import { - type Actor, - ActorFeature, - actorBuildsAtom, - actorsAtom, - createActorAtom, -} from "@rivet-gg/components/actors"; -import { createClient } from "actor-core/client"; -import { - type Actor as InspectorActor, - type ToClient, - ToClientSchema, - type ToServer, -} from "actor-core/inspector/protocol/manager"; -import { atom } from "jotai"; -import { atomEffect } from "jotai-effect"; - -const createConnection = ({ - onMessage, - onConnect, - onDisconnect, -}: { - onMessage?: (msg: ToClient) => void; - onConnect?: () => void; - onDisconnect?: () => void; -} = {}) => { - const ws = new WebSocket( - `ws://localhost:${ACTOR_CORE_MANAGER_PORT}/manager/inspect`, - ); - - const connectionTimeout = setTimeout(() => { - if (ws.readyState !== WebSocket.OPEN) { - ws.close(); - } - }, 1500); - - ws.addEventListener("open", () => { - onConnect?.(); - clearTimeout(connectionTimeout); - ws.send(JSON.stringify({ type: "info" })); - }); - - ws.addEventListener("message", (event) => { - const data = JSON.parse(event.data); - const result = ToClientSchema.safeParse(data); - if (!result.success) { - console.error("Invalid data", result.error); - return; - } - if (onMessage) { - onMessage(result.data); - } - }); - - ws.addEventListener("close", () => { - onDisconnect?.(); - }); - - ws.addEventListener("error", (event) => { - console.error("WebSocket error", event); - ws.close(); - }); - - return ws; -}; - -export const ACTOR_CORE_MANAGER_PORT = 6420; - -export const connectionStateAtom = atom<"disconnected" | "connected">( - "disconnected", -); - -export const websocketAtom = atom(null); -export const initiallyConnectedAtom = atom(false); - -export const connectionEffect = atomEffect((get, set) => { - if (get.peek(websocketAtom)) { - // effect already ran - return; - } - - let ws: WebSocket | null = null; - let reconnectTimeout: ReturnType | undefined = - undefined; - - function reconnect() { - ws = createConnection({ - onConnect: () => { - set(websocketAtom, ws); - set(initiallyConnectedAtom, true); - set(connectionStateAtom, "connected"); - - toast.success("Connected to Rivet Studio", { - id: "ws-reconnect", - }); - }, - onDisconnect: () => { - set(connectionStateAtom, "disconnected"); - - if (get.peek(initiallyConnectedAtom)) { - toast.loading("Reconnecting...", { id: "ws-reconnect" }); - } - reconnectTimeout = setTimeout(() => { - reconnect(); - }, 500); - }, - onMessage: (msg) => { - if (msg.type === "info") { - set(initiallyConnectedAtom, true); - set(actorsAtom, msg.actors.map(convertActor)); - set( - actorBuildsAtom, - msg.types.map((type) => ({ - id: type, - name: type, - tags: { current: "true" }, - contentLength: 0, - createdAt: new Date(), - })), - ); - - set(connectionStateAtom, "connected"); - - const managerEndpoint = `http://localhost:${ACTOR_CORE_MANAGER_PORT}`; - set(createActorAtom, { - endpoint: managerEndpoint, - isCreating: false, - async create(values) { - const client = createClient(managerEndpoint); - - return client.create(values.id, { - params: values.params, - create: { - tags: values.tags, - region: values.region, - }, - }); - }, - }); - } - if (msg.type === "actors") { - const existingActors = get.peek(actorsAtom); - set( - actorsAtom, - msg.actors.map((actor) => { - const existingActor = existingActors.find( - (a) => a.id === actor.id, - ); - if (existingActor) { - // remove logs from existing actor (bc logs are atom, and it will cause to recreate the atom) - const { logs, ...rest } = existingActor; - return { - ...existingActor, - ...rest, - }; - } - return convertActor(actor); - }), - ); - } - }, - }); - } - - reconnect(); - - return () => { - if (ws) { - clearTimeout(reconnectTimeout); - ws.close(); - ws = null; - } - }; -}); - -export const sendAtom = atom(null, (get, _set, msg: ToServer) => { - const ws = get(websocketAtom); - if (!ws) { - console.error("WebSocket not connected"); - return; - } - ws.send(JSON.stringify(msg)); -}); - -function convertActor(actor: InspectorActor): Actor { - return { - ...actor, - logs: atom({ - status: "pending", - logs: [], - }), - endpoint: `http://localhost:${ACTOR_CORE_MANAGER_PORT}/actors/${actor.id}`, - status: "running", - region: "local", - network: null, - runtime: null, - resources: null, - lifecycle: {}, - features: [ - ActorFeature.Console, - ActorFeature.State, - ActorFeature.Connections, - ActorFeature.Config, - ], - }; -} diff --git a/frontend/apps/studio/src/vite-env.d.ts b/frontend/apps/studio/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a0..0000000000 --- a/frontend/apps/studio/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/frontend/apps/studio/tailwind.config.js b/frontend/apps/studio/tailwind.config.js deleted file mode 100644 index b81b123464..0000000000 --- a/frontend/apps/studio/tailwind.config.js +++ /dev/null @@ -1,13 +0,0 @@ -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: [ - "./src/**/components/**/*.{ts,tsx}", - "./src/**/hooks/**/*.{ts,tsx}", - "./src/**/forms/**/*.{ts,tsx}", - "./src/**/layouts/**/*.{ts,tsx}", - "./src/**/views/**/*.{ts,tsx}", - "./src/**/routes/**/*.{ts,tsx}", - "../../../node_modules/@rivet-gg/components/**/*.{ts,tsx}", - ], - presets: [require("@rivet-gg/components/tailwind-base")], -}; diff --git a/frontend/apps/studio/tsconfig.json b/frontend/apps/studio/tsconfig.json deleted file mode 100644 index 2638acb5ff..0000000000 --- a/frontend/apps/studio/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "composite": true, - "compilerOptions": { - "skipLibCheck": true, - "target": "ESNext", - "strict": true, - "esModuleInterop": true, - "noEmit": true, - "moduleResolution": "bundler", - "module": "Preserve", - "jsx": "react-jsx", - "baseUrl": ".", - "paths": { - "@/*": ["./src/*"] - } - }, - "include": ["src", "vite.config.ts"] -} diff --git a/frontend/apps/studio/turbo.json b/frontend/apps/studio/turbo.json deleted file mode 100644 index 04f194325f..0000000000 --- a/frontend/apps/studio/turbo.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "extends": ["//"], - "tasks": { - "build": { - "env": ["VITE_APP_*"], - "outputs": ["dist/**"] - }, - "build:embedded": { - "env": ["VITE_APP_*"], - "outputs": ["dist/**"] - }, - "dev": { - "env": ["VITE_APP_*"], - "persistent": true - } - } -} diff --git a/frontend/apps/studio/vite-env.d.ts b/frontend/apps/studio/vite-env.d.ts deleted file mode 100644 index 2503b21c83..0000000000 --- a/frontend/apps/studio/vite-env.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -/// - -declare const __APP_BUILD_ID__: string; - -declare module "vite-plugin-favicons-inject" { - import type { Plugin } from "vite"; - - export default function vitePluginFaviconsInject( - iconPath: string, - // biome-ignore lint/suspicious/noExplicitAny: - options: Record, - ): Plugin; -} diff --git a/frontend/apps/studio/vite.config.ts b/frontend/apps/studio/vite.config.ts deleted file mode 100644 index b6b701fd90..0000000000 --- a/frontend/apps/studio/vite.config.ts +++ /dev/null @@ -1,75 +0,0 @@ -import * as crypto from "node:crypto"; -import path from "node:path"; -// @ts-expect-error types are missing -import { viteShikiTransformer } from "@rivet-gg/components/vite"; -import { sentryVitePlugin } from "@sentry/vite-plugin"; -import { TanStackRouterVite } from "@tanstack/router-plugin/vite"; -import react from "@vitejs/plugin-react"; -import { visualizer } from "rollup-plugin-visualizer"; -import { defineConfig } from "vite"; -// @ts-expect-error types are missing -import vitePluginFaviconsInject from "vite-plugin-favicons-inject"; - -// These are only needed in CI. They'll be undefined in dev. -const GIT_BRANCH = process.env.CF_PAGES_BRANCH; -const GIT_SHA = process.env.CF_PAGES_COMMIT_SHA; - -// https://vitejs.dev/config/ -export default defineConfig({ - base: "./", - plugins: [ - react({ - babel: { - presets: ["jotai/babel/preset"], - }, - }), - TanStackRouterVite(), - vitePluginFaviconsInject( - path.resolve(__dirname, "public", "favicon.svg"), - { - appName: "Actor Core ⋅ Studio", - theme_color: "#ff4f00", - }, - ), - process.env.SENTRY_AUTH_TOKEN - ? sentryVitePlugin({ - org: "rivet-gaming", - project: "hub", - authToken: process.env.SENTRY_AUTH_TOKEN, - release: - GIT_BRANCH === "main" ? { name: GIT_SHA } : undefined, - }) - : null, - viteShikiTransformer(), - process.env.DEBUG_BUNDLE ? visualizer() : null, - ], - server: { - port: 43708, - }, - preview: { - port: 43708, - }, - define: { - // Provide a unique build ID for cache busting - __APP_BUILD_ID__: JSON.stringify( - `${new Date().toISOString()}@${crypto.randomUUID()}`, - ), - }, - resolve: { - alias: { - "@": path.resolve(__dirname, "./src"), - }, - }, - build: { - sourcemap: true, - commonjsOptions: { - include: [/@rivet-gg\/components/, /node_modules/], - }, - }, - optimizeDeps: { - include: ["@fortawesome/*", "@rivet-gg/icons"], - }, - worker: { - format: "es", - }, -}); diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000000..92030e9e63 --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + Rivet + + +
+ + + + + diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000000..a14cda778a --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,119 @@ +{ + "name": "@rivetkit/engine-frontend", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "pnpm run '/^dev:.*/'", + "dev:inspector": "vite --config vite.inspector.config.ts", + "dev:engine": "vite --config vite.engine.config.ts", + "ts-check": "tsc --noEmit", + "build:inspector": "vite build --mode=production --config vite.inspector.config.ts", + "build:engine": "vite build --mode=production --config vite.engine.config.ts", + "preview:inspector": "vite preview --config vite.inspector.config.ts", + "preview:engine": "vite preview --config vite.engine.config.ts" + }, + "dependencies": { + "@codemirror/commands": "^6.8.1", + "@codemirror/lang-javascript": "^6.2.2", + "@codemirror/lang-json": "^6.0.1", + "@codemirror/lint": "^6.8.5", + "@codemirror/merge": "^6.10.2", + "@codemirror/state": "^6.5.2", + "@codemirror/view": "^6.28.4", + "@date-fns/utc": "^1.2.0", + "@fortawesome/fontawesome-svg-core": "^6.5.2", + "@fortawesome/free-brands-svg-icons": "^6.5.2", + "@fortawesome/free-solid-svg-icons": "^6.5.2", + "@fortawesome/react-fontawesome": "^0.2.2", + "@hookform/resolvers": "^3.3.4", + "@microsoft/fetch-event-source": "^2.0.1", + "@radix-ui/react-accordion": "^1.1.2", + "@radix-ui/react-avatar": "^1.0.4", + "@radix-ui/react-checkbox": "^1.1.5", + "@radix-ui/react-dialog": "^1.1.7", + "@radix-ui/react-dropdown-menu": "^2.1.7", + "@radix-ui/react-label": "^2.1.3", + "@radix-ui/react-popover": "^1.1.7", + "@radix-ui/react-progress": "^1.0.3", + "@radix-ui/react-radio-group": "^1.0.3", + "@radix-ui/react-scroll-area": "^1.0.5", + "@radix-ui/react-select": "^2.0.0", + "@radix-ui/react-separator": "^1.1.3", + "@radix-ui/react-slider": "^1.2.4", + "@radix-ui/react-slot": "^1.2.3", + "@radix-ui/react-switch": "^1.0.3", + "@radix-ui/react-tabs": "^1.1.4", + "@radix-ui/react-toggle": "^1.0.3", + "@radix-ui/react-toggle-group": "^1.1.1", + "@radix-ui/react-tooltip": "^1.1.1", + "@radix-ui/react-visually-hidden": "^1.0.3", + "@rivet-gg/icons": "file:./vendor/rivet-icons.tgz", + "@rivetkit/actor": "file:./vendor/rivetkit-actor.tgz", + "@rivetkit/core": "file:./vendor/rivetkit-core.tgz", + "@rivetkit/engine-api-full": "workspace:*", + "@sentry/react": "^8.26.0", + "@sentry/vite-plugin": "^2.22.2", + "@shikijs/langs": "^3.2.1", + "@shikijs/transformers": "^3.8.1", + "@tailwindcss/container-queries": "^0.1.1", + "@tailwindcss/typography": "^0.5.16", + "@tanstack/query-core": "^5.81.5", + "@tanstack/react-query": "^5.81.5", + "@tanstack/react-query-devtools": "^5.81.5", + "@tanstack/react-router": "^1.114.25", + "@tanstack/react-router-devtools": "^1.131.7", + "@tanstack/react-store": "^0.7.3", + "@tanstack/react-table": "^8.20.6", + "@tanstack/react-virtual": "^3.10.8", + "@tanstack/router-devtools": "^1.114.25", + "@tanstack/router-plugin": "^1.114.25", + "@tanstack/store": "^0.7.2", + "@tanstack/zod-adapter": "^1.114.25", + "@types/bcryptjs": "^2.4.6", + "@types/file-saver": "^2", + "@types/mdx": "^2.0.13", + "@types/node": "^20.11.30", + "@types/react": "^18.2.66", + "@types/react-dom": "^18.2.22", + "@uiw/codemirror-extensions-basic-setup": "^4.23.0", + "@uiw/codemirror-theme-github": "^4.23.0", + "@uiw/react-codemirror": "^4.23.0", + "@vitejs/plugin-react": "^4.2.1", + "actor-core": "^0.6.2", + "autoprefixer": "^10.4.19", + "bcryptjs": "^2.4.3", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.0", + "cmdk": "^1.1.1", + "date-fns": "^4.1.0", + "esast-util-from-js": "^2.0.1", + "estree-util-to-js": "^2.0.0", + "fast-deep-equal": "^3.1.3", + "fast-json-patch": "^3.1.1", + "file-saver": "^2.0.5", + "framer-motion": "^11.2.11", + "input-otp": "^1.2.3", + "lodash": "^4.17.21", + "postcss": "^8.4.38", + "posthog-js": "^1.144.2", + "react": "^19.0.0", + "react-day-picker": "8.10.1", + "react-dom": "^19.0.0", + "react-hook-form": "^7.51.1", + "react-inspector": "^6.0.2", + "react-resizable-panels": "^2.0.19", + "recharts": "^2.12.7", + "shiki": "^3.8.1", + "sonner": "^1.4.41", + "tailwind-merge": "^2.2.2", + "tailwindcss": "^3.4.1", + "tailwindcss-animate": "^1.0.7", + "typescript": "^5.5.4", + "usehooks-ts": "^3.1.0", + "vite": "^5.2.0", + "vite-plugin-favicons-inject": "^2.2.0", + "vite-tsconfig-paths": "^5.1.4", + "zod": "^3.24" + } +} diff --git a/frontend/packages/actor-core.tgz b/frontend/packages/actor-core.tgz deleted file mode 100644 index c19319b496..0000000000 --- a/frontend/packages/actor-core.tgz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5ddf59824be261c166d00af05b1f1129f8d6440ed4556788ca4065b0c6244cc2 -size 308996 diff --git a/frontend/packages/cli/cli.ts b/frontend/packages/cli/cli.ts deleted file mode 100644 index 04277d1244..0000000000 --- a/frontend/packages/cli/cli.ts +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env node -import { execFileSync } from "node:child_process"; -import os from "node:os"; -import { join } from "node:path"; - -const platform = os.platform(); - -function computeTargetFilename() { - if (platform === "win32") { - return "rivet-cli.exe"; - } - - return "rivet-cli"; -} - -try { - execFileSync( - join(__dirname, computeTargetFilename()), - process.argv.slice(2), - { - stdio: "inherit", - }, - ); -} catch (error) { - if (error.status) { - process.exit(error.status); - } - throw error; -} diff --git a/frontend/packages/cli/package.json b/frontend/packages/cli/package.json deleted file mode 100644 index c6ca3fbc2b..0000000000 --- a/frontend/packages/cli/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "rivet-cli", - "repository": { - "type": "git", - "url": "https://github.com/rivet-gg/rivet.git", - "directory": "frontend/packages/cli" - }, - "version": "25.5.3", - "bin": { - "rivet": "dist/cli.js", - "rivet-cli": "dist/cli.js" - }, - "license": "Apache-2.0", - "files": [ - "dist/cli.js", - "dist/postinstall.js", - "package.json" - ], - "sideEffects": false, - "preferGlobal": true, - "preferUnplugged": true, - "scripts": { - "build": "tsup postinstall.ts cli.ts --minify --format cjs --out-dir dist", - "postinstall": "node -e \"if (process.env.NODE_ENV !== 'production' && !require('fs').existsSync('./dist/postinstall.js')) { console.log('Skipping postinstall in dev environment'); } else { require('./dist/postinstall.js'); }\"" - }, - "devDependencies": { - "@types/node": "^22.13.4", - "tsup": "^8.3.6" - } -} diff --git a/frontend/packages/cli/postinstall.ts b/frontend/packages/cli/postinstall.ts deleted file mode 100644 index 5a72f6cc65..0000000000 --- a/frontend/packages/cli/postinstall.ts +++ /dev/null @@ -1,139 +0,0 @@ -import * as fs from "node:fs"; -import * as os from "node:os"; -import { join } from "node:path"; -import { Readable } from "node:stream"; -import type { ReadableStream } from "node:stream/web"; - -import * as pkgJson from "./package.json"; - -// dist -const BASE_PATH = join(__dirname); - -const RIVET_CLI_BINARY_PATH = join(BASE_PATH, computeTargetFilename()); -const RIVET_CLI_NODE_PATH = join(BASE_PATH, "..", pkgJson.bin.rivet); - -const artifactUrl = (version: string, name: string) => - `https://releases.rivet.gg/rivet/${version}/${name}`; - -const platform = os.platform(); -const arch = os.arch(); - -function computeBinaryFilename() { - if (platform === "linux") { - return "rivet-x86_64-unknown-linux-musl"; - } - - if (platform === "darwin") { - if (arch === "arm64") { - return "rivet-aarch64-apple-darwin"; - } - return "rivet-x86_64-apple-darwin"; - } - - if (platform === "win32") { - return "rivet-x86_64-pc-windows-gnu.exe"; - } - - throw new Error(`unsupported platform ${process.platform}`); -} - -function computeTargetFilename() { - if (platform === "win32") { - return "rivet-cli.exe"; - } - - return "rivet-cli"; -} - -function isYarn(): boolean { - const { npm_config_user_agent } = process.env; - if (npm_config_user_agent) { - return /\byarn\//.test(npm_config_user_agent); - } - return false; -} - -/** - * - * @see https://github.com/evanw/esbuild/blob/f4159a7b823cd5fe2217da2c30e8873d2f319667/lib/npm/node-install.ts#L171 - */ -function maybeOptimizePackage(binPath: string, toPath: string): void { - if (platform !== "win32" && !isYarn()) { - const tempPath = join(__dirname, "bin-rivet"); - try { - fs.linkSync(binPath, tempPath); - fs.renameSync(tempPath, toPath); - fs.unlinkSync(tempPath); - } catch (e) { - // Ignore errors here since this optimization is optional - } - } -} - -async function download(version: string) { - const binaryFilename = computeBinaryFilename(); - const url = artifactUrl(version, binaryFilename); - - console.log(`Downloading Rivet CLI ${version} for ${platform}-${arch}`); - console.log(`Binary: ${binaryFilename}`); - console.log(`URL: ${url}`); - - const response = await fetch(url); - - if (!response.ok) { - throw new Error(`unexpected response ${response.statusText}`); - } - - if (!response.body) { - throw new Error("response body is not readable stream"); - } - - let resolve: (value?: unknown) => void; - let reject: (error: unknown) => void; - const promise = new Promise((res, rej) => { - resolve = res; - reject = rej; - }); - - const writeStream = fs.createWriteStream(RIVET_CLI_BINARY_PATH); - - writeStream.on("error", (error) => { - reject(error); - }); - - writeStream.on("finish", () => { - resolve(); - }); - - Readable.fromWeb(response.body as ReadableStream).pipe(writeStream); - - return promise; -} - -async function main() { - console.log("Starting Rivet CLI installation..."); - - try { - await fs.promises.rm(RIVET_CLI_BINARY_PATH); - console.log("Cleaned up existing binary"); - } catch {} - - await download(pkgJson.version); - console.log("Download completed"); - - maybeOptimizePackage(RIVET_CLI_BINARY_PATH, RIVET_CLI_NODE_PATH); - console.log("Package optimization completed"); - - fs.chmodSync(RIVET_CLI_NODE_PATH, 0o755); - fs.chmodSync(RIVET_CLI_BINARY_PATH, 0o755); - console.log("Permissions set"); -} - -main() - .then(() => { - console.log("Rivet CLI prepared successfully"); - }) - .catch((error) => { - console.error("Failed to download and prepare Rivet CLI", error); - process.exit(1); - }); diff --git a/frontend/packages/cli/tsconfig.json b/frontend/packages/cli/tsconfig.json deleted file mode 100644 index 9b4793f843..0000000000 --- a/frontend/packages/cli/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "compilerOptions": { - "target": "ESNext", - "module": "Node16", - "strict": true, - "skipLibCheck": true, - "resolveJsonModule": true, - "moduleResolution": "node16", - "types": ["node"] - }, - "include": ["postinstall.ts"] -} diff --git a/frontend/packages/cli/turbo.json b/frontend/packages/cli/turbo.json deleted file mode 100644 index 29d4cb2625..0000000000 --- a/frontend/packages/cli/turbo.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "extends": ["//"] -} diff --git a/frontend/packages/icons/README.md b/frontend/packages/icons/README.md index 665beeb75a..90ba858898 100644 --- a/frontend/packages/icons/README.md +++ b/frontend/packages/icons/README.md @@ -26,17 +26,17 @@ Obtain a Font Awesome Pro license and set the `FONTAWESOME_PACKAGE_TOKEN` enviro 2. Run `./scripts/generateManifest.js` to generate a new `manifest.json` file. - If you're getting an error: `Could not find package @fortawesome/pro-solid-svg-icons`, 3. Commit the changes to the `manifest.json` file. -4. Run `yarn rebuild @rivet-gg/icons` to generate a new icon set with the new icons. +4. Run `pnpm rebuild @rivet-gg/icons` to generate a new icon set with the new icons. ## Troubleshooting ### Icons not showing, or icons are rectangles -Some icons used in the open-source Rivet products are part of the premium Font Awesome icon set. We can't share those icons publicly, without violating FA's Terms Of Service. By default, after adding this package to any project, a post install script generates an icon set with all premium icons replaced with simple rectangles. So, you can reference premium icons, but you won't see them. To be able to see premium icons, make sure an environment variable `FONTAWESOME_PACKAGE_TOKEN` is set when running `yarn install`. You can re-generate our icon set by running `yarn rebuild @rivet-gg/icons` if your dependencies are already installed. +Some icons used in the open-source Rivet products are part of the premium Font Awesome icon set. We can't share those icons publicly, without violating FA's Terms Of Service. By default, after adding this package to any project, a post install script generates an icon set with all premium icons replaced with simple rectangles. So, you can reference premium icons, but you won't see them. To be able to see premium icons, make sure an environment variable `FONTAWESOME_PACKAGE_TOKEN` is set when running `pnpm install`. You can re-generate our icon set by running `pnpm rebuild @rivet-gg/icons` if your dependencies are already installed. ### Can't start/build project -The description of these kinds of errors may vary. This package heavily depends on [postinstall scripts](https://yarnpkg.com/advanced/lifecycle-scripts#postinstall) from Yarn/npm. Make sure you didn't disable them accidentally. Turn on post-installation script support and run `yarn install` or `yarn rebuild @rivet-gg/icons` again. If there is still a problem, please contact us on [Discord](https://rivet.gg/discord"). +The description of these kinds of errors may vary. This package heavily depends on postinstall scripts from pnpm/npm. Make sure you didn't disable them accidentally. Turn on post-installation script support and run `pnpm install` or `pnpm rebuild @rivet-gg/icons` again. If there is still a problem, please contact us on [Discord](https://rivet.gg/discord"). ### `Could not find package @fortawesome/pro-solid-svg-icons` when generating manifest -Make sure you have installed pro icons. If you're getting an error, you can try to install them manually by running `yarn add @fortawesome/pro-solid-svg-icons`, or run `yarn install` in `src` folder. Finally run `./scripts/generateManifest.js` again. +Make sure you have installed pro icons. If you're getting an error, you can try to install them manually by running `pnpm add @fortawesome/pro-solid-svg-icons`, or run `pnpm install` in `src` folder. Finally run `./scripts/generateManifest.js` again. diff --git a/frontend/packages/icons/scripts/postinstall.js b/frontend/packages/icons/scripts/postinstall.js index 526faaaddd..5eb31dddfe 100644 --- a/frontend/packages/icons/scripts/postinstall.js +++ b/frontend/packages/icons/scripts/postinstall.js @@ -8,61 +8,52 @@ const esbuild = require("esbuild"); let hasFaToken = !!process.env.FONTAWESOME_PACKAGE_TOKEN; const sourceDir = join(__dirname, "..", "src"); +const sourceNodeModules = join(sourceDir, "node_modules"); if (!fs.existsSync(sourceDir)){ fs.mkdirSync(sourceDir, { recursive: true }); } if (process.env.FONTAWESOME_PACKAGE_TOKEN) { + // Configure auth for Font Awesome private registry via .npmrc for pnpm fs.writeFileSync( - join(sourceDir, ".yarnrc.yml"), + join(sourceDir, ".npmrc"), dedent` - nodeLinker: node-modules - - enableImmutableInstalls: false - - npmScopes: - fortawesome: - npmAlwaysAuth: true - npmRegistryServer: 'https://npm.fontawesome.com/' - npmAuthToken: \${FONTAWESOME_PACKAGE_TOKEN} - awesome.me: - npmAlwaysAuth: true - npmRegistryServer: "https://npm.fontawesome.com/" - npmAuthToken: \${FONTAWESOME_PACKAGE_TOKEN} + @fortawesome:registry=https://npm.fontawesome.com/ + @awesome.me:registry=https://npm.fontawesome.com/ + //npm.fontawesome.com/:_authToken=\${FONTAWESOME_PACKAGE_TOKEN} + //npm.fontawesome.com/:always-auth=true `, ); - fs.writeFileSync(join(sourceDir, "./package.json"), JSON.stringify({ - "name": "@rivet-gg/internal-icons", - "private": true, - "sideEffects": false, - "dependencies": { - "@awesome.me/kit-63db24046b": "^1.0.13", - "@fortawesome/pro-regular-svg-icons": "6.6.0", - "@fortawesome/pro-solid-svg-icons": "6.6.0" - } - })); - - fs.writeFileSync(join(sourceDir, "yarn.lock"), ""); + fs.writeFileSync( + join(sourceDir, "./package.json"), + JSON.stringify( + { + name: "@rivet-gg/internal-icons", + private: true, + sideEffects: false, + dependencies: { + "@awesome.me/kit-63db24046b": "^1.0.13", + "@fortawesome/pro-regular-svg-icons": "6.6.0", + "@fortawesome/pro-solid-svg-icons": "6.6.0", + }, + }, + null, + 2, + ), + ); + // Install dependencies locally without engaging the workspace to avoid recursion spawnSync( - "yarn", - ["config", "set", "-H", "enableImmutableInstalls", "false"], + "npm", + ["install", "--no-package-lock", "--silent"], { stdio: "inherit", cwd: sourceDir, + env: { ...process.env, CI: 0 }, }, ); - - spawnSync("yarn", [], { - stdio: "inherit", - cwd: sourceDir, - env: { - ...process.env, - CI: 0, - }, - }); } const banner = dedent` @@ -100,7 +91,16 @@ for (const [pkg, { icons }] of Object.entries(manifest)) { for (const { icon, aliases } of icons) { if (!indexJsSource.includes(`export { definition as ${icon} }`)) { if (hasFaToken || !isPro) { - indexJsSource += `export { definition as ${icon} } from "${pkg}/${icon}";\n`; + if (hasFaToken && isPro) { + const candidate = join(sourceNodeModules, pkg, `${icon}.js`); + if (fs.existsSync(candidate)) { + indexJsSource += `export { definition as ${icon} } from "${pkg}/${icon}";\n`; + } else { + indexJsSource += `export { definition as ${icon} } from "@fortawesome/free-solid-svg-icons/faSquare";\n`; + } + } else { + indexJsSource += `export { definition as ${icon} } from "${pkg}/${icon}";\n`; + } } else { indexJsSource += `export { definition as ${icon} } from "@fortawesome/free-solid-svg-icons/faSquare";\n`; } @@ -112,7 +112,16 @@ for (const [pkg, { icons }] of Object.entries(manifest)) { ) { continue; } - indexJsSource += `export { definition as ${alias} } from "${pkg}/${icon}";\n`; + if (hasFaToken && isPro) { + const candidate = join(sourceNodeModules, pkg, `${icon}.js`); + if (fs.existsSync(candidate)) { + indexJsSource += `export { definition as ${alias} } from "${pkg}/${icon}";\n`; + } else { + indexJsSource += `export { definition as ${alias} } from "@fortawesome/free-solid-svg-icons/faSquare";\n`; + } + } else { + indexJsSource += `export { definition as ${alias} } from "${pkg}/${icon}";\n`; + } } } } @@ -130,10 +139,27 @@ let indexTsSource = dedent` fs.writeFileSync(join(sourceDir, "index.gen.ts"), `${indexTsSource}`); async function build() { + const externals = [ + "react", + "react-dom", + "@fortawesome/react-fontawesome", + "@fortawesome/fontawesome-svg-core", + "@fortawesome/free-solid-svg-icons", + "@fortawesome/free-brands-svg-icons", + // Only treat Pro packages as external when we DON'T have a token. + // When token is present, we bundle Pro icons into dist so consumers + // don't need to resolve these at runtime from their node_modules. + // This avoids Module Not Found errors during Next.js builds. + ...(hasFaToken ? [] : [ + "@fortawesome/pro-solid-svg-icons", + "@fortawesome/pro-regular-svg-icons", + ]), + ]; + await esbuild.build({ entryPoints: [resolve(sourceDir, "index.gen.js")], outfile: resolve(__dirname, "..", "dist", "index.js"), - external: ["react", "react-dom","@fortawesome/react-fontawesome", "@fortawesome/free-solid-svg-icons","@fortawesome/fontawesome-svg-core", "@fortawesome/free-brands-svg-icons"], + external: externals, bundle: true, platform: "browser", format: "esm", diff --git a/frontend/packages/icons/src/.npmrc b/frontend/packages/icons/src/.npmrc new file mode 100644 index 0000000000..819ae6650e --- /dev/null +++ b/frontend/packages/icons/src/.npmrc @@ -0,0 +1,4 @@ +@fortawesome:registry=https://npm.fontawesome.com/ +@awesome.me:registry=https://npm.fontawesome.com/ +//npm.fontawesome.com/:_authToken=${FONTAWESOME_PACKAGE_TOKEN} +//npm.fontawesome.com/:always-auth=true \ No newline at end of file diff --git a/frontend/packages/icons/src/index.gen.js b/frontend/packages/icons/src/index.gen.js new file mode 100644 index 0000000000..1eaacddb40 --- /dev/null +++ b/frontend/packages/icons/src/index.gen.js @@ -0,0 +1,4831 @@ +// This file is generated by scripts/postinstall.js +// Do not modify this file directly +// This file does not include pro icons, all pro icons are replaced with square icon. To use pro icons, please add FONTAWESOME_PACKAGE_TOKEN to your environment and rebuild this package. + +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { createElement } from "react"; +export function Icon(props) { return createElement(FontAwesomeIcon, props)}export { definition as fa0 } from "@fortawesome/free-solid-svg-icons/fa0"; +export { definition as fa1 } from "@fortawesome/free-solid-svg-icons/fa1"; +export { definition as fa2 } from "@fortawesome/free-solid-svg-icons/fa2"; +export { definition as fa3 } from "@fortawesome/free-solid-svg-icons/fa3"; +export { definition as fa4 } from "@fortawesome/free-solid-svg-icons/fa4"; +export { definition as fa5 } from "@fortawesome/free-solid-svg-icons/fa5"; +export { definition as fa6 } from "@fortawesome/free-solid-svg-icons/fa6"; +export { definition as fa7 } from "@fortawesome/free-solid-svg-icons/fa7"; +export { definition as fa8 } from "@fortawesome/free-solid-svg-icons/fa8"; +export { definition as fa9 } from "@fortawesome/free-solid-svg-icons/fa9"; +export { definition as faA } from "@fortawesome/free-solid-svg-icons/faA"; +export { definition as faAd } from "@fortawesome/free-solid-svg-icons/faAd"; +export { definition as faAdd } from "@fortawesome/free-solid-svg-icons/faAdd"; +export { definition as faAddressBook } from "@fortawesome/free-solid-svg-icons/faAddressBook"; +export { definition as faAddressCard } from "@fortawesome/free-solid-svg-icons/faAddressCard"; +export { definition as faAdjust } from "@fortawesome/free-solid-svg-icons/faAdjust"; +export { definition as faAirFreshener } from "@fortawesome/free-solid-svg-icons/faAirFreshener"; +export { definition as faAlignCenter } from "@fortawesome/free-solid-svg-icons/faAlignCenter"; +export { definition as faAlignJustify } from "@fortawesome/free-solid-svg-icons/faAlignJustify"; +export { definition as faAlignLeft } from "@fortawesome/free-solid-svg-icons/faAlignLeft"; +export { definition as faAlignRight } from "@fortawesome/free-solid-svg-icons/faAlignRight"; +export { definition as faAllergies } from "@fortawesome/free-solid-svg-icons/faAllergies"; +export { definition as faAmbulance } from "@fortawesome/free-solid-svg-icons/faAmbulance"; +export { definition as faAmericanSignLanguageInterpreting } from "@fortawesome/free-solid-svg-icons/faAmericanSignLanguageInterpreting"; +export { definition as faAnchor } from "@fortawesome/free-solid-svg-icons/faAnchor"; +export { definition as faAnchorCircleCheck } from "@fortawesome/free-solid-svg-icons/faAnchorCircleCheck"; +export { definition as faAnchorCircleExclamation } from "@fortawesome/free-solid-svg-icons/faAnchorCircleExclamation"; +export { definition as faAnchorCircleXmark } from "@fortawesome/free-solid-svg-icons/faAnchorCircleXmark"; +export { definition as faAnchorLock } from "@fortawesome/free-solid-svg-icons/faAnchorLock"; +export { definition as faAngleDoubleDown } from "@fortawesome/free-solid-svg-icons/faAngleDoubleDown"; +export { definition as faAngleDoubleLeft } from "@fortawesome/free-solid-svg-icons/faAngleDoubleLeft"; +export { definition as faAngleDoubleRight } from "@fortawesome/free-solid-svg-icons/faAngleDoubleRight"; +export { definition as faAngleDoubleUp } from "@fortawesome/free-solid-svg-icons/faAngleDoubleUp"; +export { definition as faAngleDown } from "@fortawesome/free-solid-svg-icons/faAngleDown"; +export { definition as faAngleLeft } from "@fortawesome/free-solid-svg-icons/faAngleLeft"; +export { definition as faAngleRight } from "@fortawesome/free-solid-svg-icons/faAngleRight"; +export { definition as faAngleUp } from "@fortawesome/free-solid-svg-icons/faAngleUp"; +export { definition as faAnglesDown } from "@fortawesome/free-solid-svg-icons/faAnglesDown"; +export { definition as faAnglesLeft } from "@fortawesome/free-solid-svg-icons/faAnglesLeft"; +export { definition as faAnglesRight } from "@fortawesome/free-solid-svg-icons/faAnglesRight"; +export { definition as faAnglesUp } from "@fortawesome/free-solid-svg-icons/faAnglesUp"; +export { definition as faAngry } from "@fortawesome/free-solid-svg-icons/faAngry"; +export { definition as faAnkh } from "@fortawesome/free-solid-svg-icons/faAnkh"; +export { definition as faAppleAlt } from "@fortawesome/free-solid-svg-icons/faAppleAlt"; +export { definition as faAppleWhole } from "@fortawesome/free-solid-svg-icons/faAppleWhole"; +export { definition as faArchive } from "@fortawesome/free-solid-svg-icons/faArchive"; +export { definition as faArchway } from "@fortawesome/free-solid-svg-icons/faArchway"; +export { definition as faAreaChart } from "@fortawesome/free-solid-svg-icons/faAreaChart"; +export { definition as faArrowAltCircleDown } from "@fortawesome/free-solid-svg-icons/faArrowAltCircleDown"; +export { definition as faArrowAltCircleLeft } from "@fortawesome/free-solid-svg-icons/faArrowAltCircleLeft"; +export { definition as faArrowAltCircleRight } from "@fortawesome/free-solid-svg-icons/faArrowAltCircleRight"; +export { definition as faArrowAltCircleUp } from "@fortawesome/free-solid-svg-icons/faArrowAltCircleUp"; +export { definition as faArrowCircleDown } from "@fortawesome/free-solid-svg-icons/faArrowCircleDown"; +export { definition as faArrowCircleLeft } from "@fortawesome/free-solid-svg-icons/faArrowCircleLeft"; +export { definition as faArrowCircleRight } from "@fortawesome/free-solid-svg-icons/faArrowCircleRight"; +export { definition as faArrowCircleUp } from "@fortawesome/free-solid-svg-icons/faArrowCircleUp"; +export { definition as faArrowDown } from "@fortawesome/free-solid-svg-icons/faArrowDown"; +export { definition as faArrowDown19 } from "@fortawesome/free-solid-svg-icons/faArrowDown19"; +export { definition as faArrowDown91 } from "@fortawesome/free-solid-svg-icons/faArrowDown91"; +export { definition as faArrowDownAZ } from "@fortawesome/free-solid-svg-icons/faArrowDownAZ"; +export { definition as faArrowDownLong } from "@fortawesome/free-solid-svg-icons/faArrowDownLong"; +export { definition as faArrowDownShortWide } from "@fortawesome/free-solid-svg-icons/faArrowDownShortWide"; +export { definition as faArrowDownUpAcrossLine } from "@fortawesome/free-solid-svg-icons/faArrowDownUpAcrossLine"; +export { definition as faArrowDownUpLock } from "@fortawesome/free-solid-svg-icons/faArrowDownUpLock"; +export { definition as faArrowDownWideShort } from "@fortawesome/free-solid-svg-icons/faArrowDownWideShort"; +export { definition as faArrowDownZA } from "@fortawesome/free-solid-svg-icons/faArrowDownZA"; +export { definition as faArrowLeft } from "@fortawesome/free-solid-svg-icons/faArrowLeft"; +export { definition as faArrowLeftLong } from "@fortawesome/free-solid-svg-icons/faArrowLeftLong"; +export { definition as faArrowLeftRotate } from "@fortawesome/free-solid-svg-icons/faArrowLeftRotate"; +export { definition as faArrowPointer } from "@fortawesome/free-solid-svg-icons/faArrowPointer"; +export { definition as faArrowRight } from "@fortawesome/free-solid-svg-icons/faArrowRight"; +export { definition as faArrowRightArrowLeft } from "@fortawesome/free-solid-svg-icons/faArrowRightArrowLeft"; +export { definition as faArrowRightFromBracket } from "@fortawesome/free-solid-svg-icons/faArrowRightFromBracket"; +export { definition as faArrowRightFromFile } from "@fortawesome/free-solid-svg-icons/faArrowRightFromFile"; +export { definition as faArrowRightLong } from "@fortawesome/free-solid-svg-icons/faArrowRightLong"; +export { definition as faArrowRightRotate } from "@fortawesome/free-solid-svg-icons/faArrowRightRotate"; +export { definition as faArrowRightToBracket } from "@fortawesome/free-solid-svg-icons/faArrowRightToBracket"; +export { definition as faArrowRightToCity } from "@fortawesome/free-solid-svg-icons/faArrowRightToCity"; +export { definition as faArrowRightToFile } from "@fortawesome/free-solid-svg-icons/faArrowRightToFile"; +export { definition as faArrowRotateBack } from "@fortawesome/free-solid-svg-icons/faArrowRotateBack"; +export { definition as faArrowRotateBackward } from "@fortawesome/free-solid-svg-icons/faArrowRotateBackward"; +export { definition as faArrowRotateForward } from "@fortawesome/free-solid-svg-icons/faArrowRotateForward"; +export { definition as faArrowRotateLeft } from "@fortawesome/free-solid-svg-icons/faArrowRotateLeft"; +export { definition as faArrowRotateRight } from "@fortawesome/free-solid-svg-icons/faArrowRotateRight"; +export { definition as faArrowTrendDown } from "@fortawesome/free-solid-svg-icons/faArrowTrendDown"; +export { definition as faArrowTrendUp } from "@fortawesome/free-solid-svg-icons/faArrowTrendUp"; +export { definition as faArrowTurnDown } from "@fortawesome/free-solid-svg-icons/faArrowTurnDown"; +export { definition as faArrowTurnUp } from "@fortawesome/free-solid-svg-icons/faArrowTurnUp"; +export { definition as faArrowUp } from "@fortawesome/free-solid-svg-icons/faArrowUp"; +export { definition as faArrowUp19 } from "@fortawesome/free-solid-svg-icons/faArrowUp19"; +export { definition as faArrowUp91 } from "@fortawesome/free-solid-svg-icons/faArrowUp91"; +export { definition as faArrowUpAZ } from "@fortawesome/free-solid-svg-icons/faArrowUpAZ"; +export { definition as faArrowUpFromBracket } from "@fortawesome/free-solid-svg-icons/faArrowUpFromBracket"; +export { definition as faArrowUpFromGroundWater } from "@fortawesome/free-solid-svg-icons/faArrowUpFromGroundWater"; +export { definition as faArrowUpFromWaterPump } from "@fortawesome/free-solid-svg-icons/faArrowUpFromWaterPump"; +export { definition as faArrowUpLong } from "@fortawesome/free-solid-svg-icons/faArrowUpLong"; +export { definition as faArrowUpRightDots } from "@fortawesome/free-solid-svg-icons/faArrowUpRightDots"; +export { definition as faArrowUpRightFromSquare } from "@fortawesome/free-solid-svg-icons/faArrowUpRightFromSquare"; +export { definition as faArrowUpShortWide } from "@fortawesome/free-solid-svg-icons/faArrowUpShortWide"; +export { definition as faArrowUpWideShort } from "@fortawesome/free-solid-svg-icons/faArrowUpWideShort"; +export { definition as faArrowUpZA } from "@fortawesome/free-solid-svg-icons/faArrowUpZA"; +export { definition as faArrows } from "@fortawesome/free-solid-svg-icons/faArrows"; +export { definition as faArrowsAlt } from "@fortawesome/free-solid-svg-icons/faArrowsAlt"; +export { definition as faArrowsAltH } from "@fortawesome/free-solid-svg-icons/faArrowsAltH"; +export { definition as faArrowsAltV } from "@fortawesome/free-solid-svg-icons/faArrowsAltV"; +export { definition as faArrowsDownToLine } from "@fortawesome/free-solid-svg-icons/faArrowsDownToLine"; +export { definition as faArrowsDownToPeople } from "@fortawesome/free-solid-svg-icons/faArrowsDownToPeople"; +export { definition as faArrowsH } from "@fortawesome/free-solid-svg-icons/faArrowsH"; +export { definition as faArrowsLeftRight } from "@fortawesome/free-solid-svg-icons/faArrowsLeftRight"; +export { definition as faArrowsLeftRightToLine } from "@fortawesome/free-solid-svg-icons/faArrowsLeftRightToLine"; +export { definition as faArrowsRotate } from "@fortawesome/free-solid-svg-icons/faArrowsRotate"; +export { definition as faArrowsSpin } from "@fortawesome/free-solid-svg-icons/faArrowsSpin"; +export { definition as faArrowsSplitUpAndLeft } from "@fortawesome/free-solid-svg-icons/faArrowsSplitUpAndLeft"; +export { definition as faArrowsToCircle } from "@fortawesome/free-solid-svg-icons/faArrowsToCircle"; +export { definition as faArrowsToDot } from "@fortawesome/free-solid-svg-icons/faArrowsToDot"; +export { definition as faArrowsToEye } from "@fortawesome/free-solid-svg-icons/faArrowsToEye"; +export { definition as faArrowsTurnRight } from "@fortawesome/free-solid-svg-icons/faArrowsTurnRight"; +export { definition as faArrowsTurnToDots } from "@fortawesome/free-solid-svg-icons/faArrowsTurnToDots"; +export { definition as faArrowsUpDown } from "@fortawesome/free-solid-svg-icons/faArrowsUpDown"; +export { definition as faArrowsUpDownLeftRight } from "@fortawesome/free-solid-svg-icons/faArrowsUpDownLeftRight"; +export { definition as faArrowsUpToLine } from "@fortawesome/free-solid-svg-icons/faArrowsUpToLine"; +export { definition as faArrowsV } from "@fortawesome/free-solid-svg-icons/faArrowsV"; +export { definition as faAslInterpreting } from "@fortawesome/free-solid-svg-icons/faAslInterpreting"; +export { definition as faAssistiveListeningSystems } from "@fortawesome/free-solid-svg-icons/faAssistiveListeningSystems"; +export { definition as faAsterisk } from "@fortawesome/free-solid-svg-icons/faAsterisk"; +export { definition as faAt } from "@fortawesome/free-solid-svg-icons/faAt"; +export { definition as faAtlas } from "@fortawesome/free-solid-svg-icons/faAtlas"; +export { definition as faAtom } from "@fortawesome/free-solid-svg-icons/faAtom"; +export { definition as faAudioDescription } from "@fortawesome/free-solid-svg-icons/faAudioDescription"; +export { definition as faAustralSign } from "@fortawesome/free-solid-svg-icons/faAustralSign"; +export { definition as faAutomobile } from "@fortawesome/free-solid-svg-icons/faAutomobile"; +export { definition as faAward } from "@fortawesome/free-solid-svg-icons/faAward"; +export { definition as faB } from "@fortawesome/free-solid-svg-icons/faB"; +export { definition as faBaby } from "@fortawesome/free-solid-svg-icons/faBaby"; +export { definition as faBabyCarriage } from "@fortawesome/free-solid-svg-icons/faBabyCarriage"; +export { definition as faBackspace } from "@fortawesome/free-solid-svg-icons/faBackspace"; +export { definition as faBackward } from "@fortawesome/free-solid-svg-icons/faBackward"; +export { definition as faBackwardFast } from "@fortawesome/free-solid-svg-icons/faBackwardFast"; +export { definition as faBackwardStep } from "@fortawesome/free-solid-svg-icons/faBackwardStep"; +export { definition as faBacon } from "@fortawesome/free-solid-svg-icons/faBacon"; +export { definition as faBacteria } from "@fortawesome/free-solid-svg-icons/faBacteria"; +export { definition as faBacterium } from "@fortawesome/free-solid-svg-icons/faBacterium"; +export { definition as faBagShopping } from "@fortawesome/free-solid-svg-icons/faBagShopping"; +export { definition as faBahai } from "@fortawesome/free-solid-svg-icons/faBahai"; +export { definition as faBahtSign } from "@fortawesome/free-solid-svg-icons/faBahtSign"; +export { definition as faBalanceScale } from "@fortawesome/free-solid-svg-icons/faBalanceScale"; +export { definition as faBalanceScaleLeft } from "@fortawesome/free-solid-svg-icons/faBalanceScaleLeft"; +export { definition as faBalanceScaleRight } from "@fortawesome/free-solid-svg-icons/faBalanceScaleRight"; +export { definition as faBan } from "@fortawesome/free-solid-svg-icons/faBan"; +export { definition as faBanSmoking } from "@fortawesome/free-solid-svg-icons/faBanSmoking"; +export { definition as faBandAid } from "@fortawesome/free-solid-svg-icons/faBandAid"; +export { definition as faBandage } from "@fortawesome/free-solid-svg-icons/faBandage"; +export { definition as faBangladeshiTakaSign } from "@fortawesome/free-solid-svg-icons/faBangladeshiTakaSign"; +export { definition as faBank } from "@fortawesome/free-solid-svg-icons/faBank"; +export { definition as faBarChart } from "@fortawesome/free-solid-svg-icons/faBarChart"; +export { definition as faBarcode } from "@fortawesome/free-solid-svg-icons/faBarcode"; +export { definition as faBars } from "@fortawesome/free-solid-svg-icons/faBars"; +export { definition as faBarsProgress } from "@fortawesome/free-solid-svg-icons/faBarsProgress"; +export { definition as faBarsStaggered } from "@fortawesome/free-solid-svg-icons/faBarsStaggered"; +export { definition as faBaseball } from "@fortawesome/free-solid-svg-icons/faBaseball"; +export { definition as faBaseballBall } from "@fortawesome/free-solid-svg-icons/faBaseballBall"; +export { definition as faBaseballBatBall } from "@fortawesome/free-solid-svg-icons/faBaseballBatBall"; +export { definition as faBasketShopping } from "@fortawesome/free-solid-svg-icons/faBasketShopping"; +export { definition as faBasketball } from "@fortawesome/free-solid-svg-icons/faBasketball"; +export { definition as faBasketballBall } from "@fortawesome/free-solid-svg-icons/faBasketballBall"; +export { definition as faBath } from "@fortawesome/free-solid-svg-icons/faBath"; +export { definition as faBathtub } from "@fortawesome/free-solid-svg-icons/faBathtub"; +export { definition as faBattery } from "@fortawesome/free-solid-svg-icons/faBattery"; +export { definition as faBattery0 } from "@fortawesome/free-solid-svg-icons/faBattery0"; +export { definition as faBattery2 } from "@fortawesome/free-solid-svg-icons/faBattery2"; +export { definition as faBattery3 } from "@fortawesome/free-solid-svg-icons/faBattery3"; +export { definition as faBattery4 } from "@fortawesome/free-solid-svg-icons/faBattery4"; +export { definition as faBattery5 } from "@fortawesome/free-solid-svg-icons/faBattery5"; +export { definition as faBatteryCar } from "@fortawesome/free-solid-svg-icons/faBatteryCar"; +export { definition as faBatteryEmpty } from "@fortawesome/free-solid-svg-icons/faBatteryEmpty"; +export { definition as faBatteryFull } from "@fortawesome/free-solid-svg-icons/faBatteryFull"; +export { definition as faBatteryHalf } from "@fortawesome/free-solid-svg-icons/faBatteryHalf"; +export { definition as faBatteryQuarter } from "@fortawesome/free-solid-svg-icons/faBatteryQuarter"; +export { definition as faBatteryThreeQuarters } from "@fortawesome/free-solid-svg-icons/faBatteryThreeQuarters"; +export { definition as faBed } from "@fortawesome/free-solid-svg-icons/faBed"; +export { definition as faBedPulse } from "@fortawesome/free-solid-svg-icons/faBedPulse"; +export { definition as faBeer } from "@fortawesome/free-solid-svg-icons/faBeer"; +export { definition as faBeerMugEmpty } from "@fortawesome/free-solid-svg-icons/faBeerMugEmpty"; +export { definition as faBell } from "@fortawesome/free-solid-svg-icons/faBell"; +export { definition as faBellConcierge } from "@fortawesome/free-solid-svg-icons/faBellConcierge"; +export { definition as faBellSlash } from "@fortawesome/free-solid-svg-icons/faBellSlash"; +export { definition as faBezierCurve } from "@fortawesome/free-solid-svg-icons/faBezierCurve"; +export { definition as faBible } from "@fortawesome/free-solid-svg-icons/faBible"; +export { definition as faBicycle } from "@fortawesome/free-solid-svg-icons/faBicycle"; +export { definition as faBiking } from "@fortawesome/free-solid-svg-icons/faBiking"; +export { definition as faBinoculars } from "@fortawesome/free-solid-svg-icons/faBinoculars"; +export { definition as faBiohazard } from "@fortawesome/free-solid-svg-icons/faBiohazard"; +export { definition as faBirthdayCake } from "@fortawesome/free-solid-svg-icons/faBirthdayCake"; +export { definition as faBitcoinSign } from "@fortawesome/free-solid-svg-icons/faBitcoinSign"; +export { definition as faBlackboard } from "@fortawesome/free-solid-svg-icons/faBlackboard"; +export { definition as faBlender } from "@fortawesome/free-solid-svg-icons/faBlender"; +export { definition as faBlenderPhone } from "@fortawesome/free-solid-svg-icons/faBlenderPhone"; +export { definition as faBlind } from "@fortawesome/free-solid-svg-icons/faBlind"; +export { definition as faBlog } from "@fortawesome/free-solid-svg-icons/faBlog"; +export { definition as faBold } from "@fortawesome/free-solid-svg-icons/faBold"; +export { definition as faBolt } from "@fortawesome/free-solid-svg-icons/faBolt"; +export { definition as faBoltLightning } from "@fortawesome/free-solid-svg-icons/faBoltLightning"; +export { definition as faBomb } from "@fortawesome/free-solid-svg-icons/faBomb"; +export { definition as faBone } from "@fortawesome/free-solid-svg-icons/faBone"; +export { definition as faBong } from "@fortawesome/free-solid-svg-icons/faBong"; +export { definition as faBook } from "@fortawesome/free-solid-svg-icons/faBook"; +export { definition as faBookAtlas } from "@fortawesome/free-solid-svg-icons/faBookAtlas"; +export { definition as faBookBible } from "@fortawesome/free-solid-svg-icons/faBookBible"; +export { definition as faBookBookmark } from "@fortawesome/free-solid-svg-icons/faBookBookmark"; +export { definition as faBookDead } from "@fortawesome/free-solid-svg-icons/faBookDead"; +export { definition as faBookJournalWhills } from "@fortawesome/free-solid-svg-icons/faBookJournalWhills"; +export { definition as faBookMedical } from "@fortawesome/free-solid-svg-icons/faBookMedical"; +export { definition as faBookOpen } from "@fortawesome/free-solid-svg-icons/faBookOpen"; +export { definition as faBookOpenReader } from "@fortawesome/free-solid-svg-icons/faBookOpenReader"; +export { definition as faBookQuran } from "@fortawesome/free-solid-svg-icons/faBookQuran"; +export { definition as faBookReader } from "@fortawesome/free-solid-svg-icons/faBookReader"; +export { definition as faBookSkull } from "@fortawesome/free-solid-svg-icons/faBookSkull"; +export { definition as faBookTanakh } from "@fortawesome/free-solid-svg-icons/faBookTanakh"; +export { definition as faBookmark } from "@fortawesome/free-solid-svg-icons/faBookmark"; +export { definition as faBorderAll } from "@fortawesome/free-solid-svg-icons/faBorderAll"; +export { definition as faBorderNone } from "@fortawesome/free-solid-svg-icons/faBorderNone"; +export { definition as faBorderStyle } from "@fortawesome/free-solid-svg-icons/faBorderStyle"; +export { definition as faBorderTopLeft } from "@fortawesome/free-solid-svg-icons/faBorderTopLeft"; +export { definition as faBoreHole } from "@fortawesome/free-solid-svg-icons/faBoreHole"; +export { definition as faBottleDroplet } from "@fortawesome/free-solid-svg-icons/faBottleDroplet"; +export { definition as faBottleWater } from "@fortawesome/free-solid-svg-icons/faBottleWater"; +export { definition as faBowlFood } from "@fortawesome/free-solid-svg-icons/faBowlFood"; +export { definition as faBowlRice } from "@fortawesome/free-solid-svg-icons/faBowlRice"; +export { definition as faBowlingBall } from "@fortawesome/free-solid-svg-icons/faBowlingBall"; +export { definition as faBox } from "@fortawesome/free-solid-svg-icons/faBox"; +export { definition as faBoxArchive } from "@fortawesome/free-solid-svg-icons/faBoxArchive"; +export { definition as faBoxOpen } from "@fortawesome/free-solid-svg-icons/faBoxOpen"; +export { definition as faBoxTissue } from "@fortawesome/free-solid-svg-icons/faBoxTissue"; +export { definition as faBoxes } from "@fortawesome/free-solid-svg-icons/faBoxes"; +export { definition as faBoxesAlt } from "@fortawesome/free-solid-svg-icons/faBoxesAlt"; +export { definition as faBoxesPacking } from "@fortawesome/free-solid-svg-icons/faBoxesPacking"; +export { definition as faBoxesStacked } from "@fortawesome/free-solid-svg-icons/faBoxesStacked"; +export { definition as faBraille } from "@fortawesome/free-solid-svg-icons/faBraille"; +export { definition as faBrain } from "@fortawesome/free-solid-svg-icons/faBrain"; +export { definition as faBrazilianRealSign } from "@fortawesome/free-solid-svg-icons/faBrazilianRealSign"; +export { definition as faBreadSlice } from "@fortawesome/free-solid-svg-icons/faBreadSlice"; +export { definition as faBridge } from "@fortawesome/free-solid-svg-icons/faBridge"; +export { definition as faBridgeCircleCheck } from "@fortawesome/free-solid-svg-icons/faBridgeCircleCheck"; +export { definition as faBridgeCircleExclamation } from "@fortawesome/free-solid-svg-icons/faBridgeCircleExclamation"; +export { definition as faBridgeCircleXmark } from "@fortawesome/free-solid-svg-icons/faBridgeCircleXmark"; +export { definition as faBridgeLock } from "@fortawesome/free-solid-svg-icons/faBridgeLock"; +export { definition as faBridgeWater } from "@fortawesome/free-solid-svg-icons/faBridgeWater"; +export { definition as faBriefcase } from "@fortawesome/free-solid-svg-icons/faBriefcase"; +export { definition as faBriefcaseClock } from "@fortawesome/free-solid-svg-icons/faBriefcaseClock"; +export { definition as faBriefcaseMedical } from "@fortawesome/free-solid-svg-icons/faBriefcaseMedical"; +export { definition as faBroadcastTower } from "@fortawesome/free-solid-svg-icons/faBroadcastTower"; +export { definition as faBroom } from "@fortawesome/free-solid-svg-icons/faBroom"; +export { definition as faBroomBall } from "@fortawesome/free-solid-svg-icons/faBroomBall"; +export { definition as faBrush } from "@fortawesome/free-solid-svg-icons/faBrush"; +export { definition as faBucket } from "@fortawesome/free-solid-svg-icons/faBucket"; +export { definition as faBug } from "@fortawesome/free-solid-svg-icons/faBug"; +export { definition as faBugSlash } from "@fortawesome/free-solid-svg-icons/faBugSlash"; +export { definition as faBugs } from "@fortawesome/free-solid-svg-icons/faBugs"; +export { definition as faBuilding } from "@fortawesome/free-solid-svg-icons/faBuilding"; +export { definition as faBuildingCircleArrowRight } from "@fortawesome/free-solid-svg-icons/faBuildingCircleArrowRight"; +export { definition as faBuildingCircleCheck } from "@fortawesome/free-solid-svg-icons/faBuildingCircleCheck"; +export { definition as faBuildingCircleExclamation } from "@fortawesome/free-solid-svg-icons/faBuildingCircleExclamation"; +export { definition as faBuildingCircleXmark } from "@fortawesome/free-solid-svg-icons/faBuildingCircleXmark"; +export { definition as faBuildingColumns } from "@fortawesome/free-solid-svg-icons/faBuildingColumns"; +export { definition as faBuildingFlag } from "@fortawesome/free-solid-svg-icons/faBuildingFlag"; +export { definition as faBuildingLock } from "@fortawesome/free-solid-svg-icons/faBuildingLock"; +export { definition as faBuildingNgo } from "@fortawesome/free-solid-svg-icons/faBuildingNgo"; +export { definition as faBuildingShield } from "@fortawesome/free-solid-svg-icons/faBuildingShield"; +export { definition as faBuildingUn } from "@fortawesome/free-solid-svg-icons/faBuildingUn"; +export { definition as faBuildingUser } from "@fortawesome/free-solid-svg-icons/faBuildingUser"; +export { definition as faBuildingWheat } from "@fortawesome/free-solid-svg-icons/faBuildingWheat"; +export { definition as faBullhorn } from "@fortawesome/free-solid-svg-icons/faBullhorn"; +export { definition as faBullseye } from "@fortawesome/free-solid-svg-icons/faBullseye"; +export { definition as faBurger } from "@fortawesome/free-solid-svg-icons/faBurger"; +export { definition as faBurn } from "@fortawesome/free-solid-svg-icons/faBurn"; +export { definition as faBurst } from "@fortawesome/free-solid-svg-icons/faBurst"; +export { definition as faBus } from "@fortawesome/free-solid-svg-icons/faBus"; +export { definition as faBusAlt } from "@fortawesome/free-solid-svg-icons/faBusAlt"; +export { definition as faBusSimple } from "@fortawesome/free-solid-svg-icons/faBusSimple"; +export { definition as faBusinessTime } from "@fortawesome/free-solid-svg-icons/faBusinessTime"; +export { definition as faC } from "@fortawesome/free-solid-svg-icons/faC"; +export { definition as faCab } from "@fortawesome/free-solid-svg-icons/faCab"; +export { definition as faCableCar } from "@fortawesome/free-solid-svg-icons/faCableCar"; +export { definition as faCake } from "@fortawesome/free-solid-svg-icons/faCake"; +export { definition as faCakeCandles } from "@fortawesome/free-solid-svg-icons/faCakeCandles"; +export { definition as faCalculator } from "@fortawesome/free-solid-svg-icons/faCalculator"; +export { definition as faCalendar } from "@fortawesome/free-solid-svg-icons/faCalendar"; +export { definition as faCalendarAlt } from "@fortawesome/free-solid-svg-icons/faCalendarAlt"; +export { definition as faCalendarCheck } from "@fortawesome/free-solid-svg-icons/faCalendarCheck"; +export { definition as faCalendarDay } from "@fortawesome/free-solid-svg-icons/faCalendarDay"; +export { definition as faCalendarDays } from "@fortawesome/free-solid-svg-icons/faCalendarDays"; +export { definition as faCalendarMinus } from "@fortawesome/free-solid-svg-icons/faCalendarMinus"; +export { definition as faCalendarPlus } from "@fortawesome/free-solid-svg-icons/faCalendarPlus"; +export { definition as faCalendarTimes } from "@fortawesome/free-solid-svg-icons/faCalendarTimes"; +export { definition as faCalendarWeek } from "@fortawesome/free-solid-svg-icons/faCalendarWeek"; +export { definition as faCalendarXmark } from "@fortawesome/free-solid-svg-icons/faCalendarXmark"; +export { definition as faCamera } from "@fortawesome/free-solid-svg-icons/faCamera"; +export { definition as faCameraAlt } from "@fortawesome/free-solid-svg-icons/faCameraAlt"; +export { definition as faCameraRetro } from "@fortawesome/free-solid-svg-icons/faCameraRetro"; +export { definition as faCameraRotate } from "@fortawesome/free-solid-svg-icons/faCameraRotate"; +export { definition as faCampground } from "@fortawesome/free-solid-svg-icons/faCampground"; +export { definition as faCancel } from "@fortawesome/free-solid-svg-icons/faCancel"; +export { definition as faCandyCane } from "@fortawesome/free-solid-svg-icons/faCandyCane"; +export { definition as faCannabis } from "@fortawesome/free-solid-svg-icons/faCannabis"; +export { definition as faCapsules } from "@fortawesome/free-solid-svg-icons/faCapsules"; +export { definition as faCar } from "@fortawesome/free-solid-svg-icons/faCar"; +export { definition as faCarAlt } from "@fortawesome/free-solid-svg-icons/faCarAlt"; +export { definition as faCarBattery } from "@fortawesome/free-solid-svg-icons/faCarBattery"; +export { definition as faCarBurst } from "@fortawesome/free-solid-svg-icons/faCarBurst"; +export { definition as faCarCrash } from "@fortawesome/free-solid-svg-icons/faCarCrash"; +export { definition as faCarOn } from "@fortawesome/free-solid-svg-icons/faCarOn"; +export { definition as faCarRear } from "@fortawesome/free-solid-svg-icons/faCarRear"; +export { definition as faCarSide } from "@fortawesome/free-solid-svg-icons/faCarSide"; +export { definition as faCarTunnel } from "@fortawesome/free-solid-svg-icons/faCarTunnel"; +export { definition as faCaravan } from "@fortawesome/free-solid-svg-icons/faCaravan"; +export { definition as faCaretDown } from "@fortawesome/free-solid-svg-icons/faCaretDown"; +export { definition as faCaretLeft } from "@fortawesome/free-solid-svg-icons/faCaretLeft"; +export { definition as faCaretRight } from "@fortawesome/free-solid-svg-icons/faCaretRight"; +export { definition as faCaretSquareDown } from "@fortawesome/free-solid-svg-icons/faCaretSquareDown"; +export { definition as faCaretSquareLeft } from "@fortawesome/free-solid-svg-icons/faCaretSquareLeft"; +export { definition as faCaretSquareRight } from "@fortawesome/free-solid-svg-icons/faCaretSquareRight"; +export { definition as faCaretSquareUp } from "@fortawesome/free-solid-svg-icons/faCaretSquareUp"; +export { definition as faCaretUp } from "@fortawesome/free-solid-svg-icons/faCaretUp"; +export { definition as faCarriageBaby } from "@fortawesome/free-solid-svg-icons/faCarriageBaby"; +export { definition as faCarrot } from "@fortawesome/free-solid-svg-icons/faCarrot"; +export { definition as faCartArrowDown } from "@fortawesome/free-solid-svg-icons/faCartArrowDown"; +export { definition as faCartFlatbed } from "@fortawesome/free-solid-svg-icons/faCartFlatbed"; +export { definition as faCartFlatbedSuitcase } from "@fortawesome/free-solid-svg-icons/faCartFlatbedSuitcase"; +export { definition as faCartPlus } from "@fortawesome/free-solid-svg-icons/faCartPlus"; +export { definition as faCartShopping } from "@fortawesome/free-solid-svg-icons/faCartShopping"; +export { definition as faCashRegister } from "@fortawesome/free-solid-svg-icons/faCashRegister"; +export { definition as faCat } from "@fortawesome/free-solid-svg-icons/faCat"; +export { definition as faCediSign } from "@fortawesome/free-solid-svg-icons/faCediSign"; +export { definition as faCentSign } from "@fortawesome/free-solid-svg-icons/faCentSign"; +export { definition as faCertificate } from "@fortawesome/free-solid-svg-icons/faCertificate"; +export { definition as faChain } from "@fortawesome/free-solid-svg-icons/faChain"; +export { definition as faChainBroken } from "@fortawesome/free-solid-svg-icons/faChainBroken"; +export { definition as faChainSlash } from "@fortawesome/free-solid-svg-icons/faChainSlash"; +export { definition as faChair } from "@fortawesome/free-solid-svg-icons/faChair"; +export { definition as faChalkboard } from "@fortawesome/free-solid-svg-icons/faChalkboard"; +export { definition as faChalkboardTeacher } from "@fortawesome/free-solid-svg-icons/faChalkboardTeacher"; +export { definition as faChalkboardUser } from "@fortawesome/free-solid-svg-icons/faChalkboardUser"; +export { definition as faChampagneGlasses } from "@fortawesome/free-solid-svg-icons/faChampagneGlasses"; +export { definition as faChargingStation } from "@fortawesome/free-solid-svg-icons/faChargingStation"; +export { definition as faChartArea } from "@fortawesome/free-solid-svg-icons/faChartArea"; +export { definition as faChartBar } from "@fortawesome/free-solid-svg-icons/faChartBar"; +export { definition as faChartColumn } from "@fortawesome/free-solid-svg-icons/faChartColumn"; +export { definition as faChartDiagram } from "@fortawesome/free-solid-svg-icons/faChartDiagram"; +export { definition as faChartGantt } from "@fortawesome/free-solid-svg-icons/faChartGantt"; +export { definition as faChartLine } from "@fortawesome/free-solid-svg-icons/faChartLine"; +export { definition as faChartPie } from "@fortawesome/free-solid-svg-icons/faChartPie"; +export { definition as faChartSimple } from "@fortawesome/free-solid-svg-icons/faChartSimple"; +export { definition as faCheck } from "@fortawesome/free-solid-svg-icons/faCheck"; +export { definition as faCheckCircle } from "@fortawesome/free-solid-svg-icons/faCheckCircle"; +export { definition as faCheckDouble } from "@fortawesome/free-solid-svg-icons/faCheckDouble"; +export { definition as faCheckSquare } from "@fortawesome/free-solid-svg-icons/faCheckSquare"; +export { definition as faCheckToSlot } from "@fortawesome/free-solid-svg-icons/faCheckToSlot"; +export { definition as faCheese } from "@fortawesome/free-solid-svg-icons/faCheese"; +export { definition as faChess } from "@fortawesome/free-solid-svg-icons/faChess"; +export { definition as faChessBishop } from "@fortawesome/free-solid-svg-icons/faChessBishop"; +export { definition as faChessBoard } from "@fortawesome/free-solid-svg-icons/faChessBoard"; +export { definition as faChessKing } from "@fortawesome/free-solid-svg-icons/faChessKing"; +export { definition as faChessKnight } from "@fortawesome/free-solid-svg-icons/faChessKnight"; +export { definition as faChessPawn } from "@fortawesome/free-solid-svg-icons/faChessPawn"; +export { definition as faChessQueen } from "@fortawesome/free-solid-svg-icons/faChessQueen"; +export { definition as faChessRook } from "@fortawesome/free-solid-svg-icons/faChessRook"; +export { definition as faChevronCircleDown } from "@fortawesome/free-solid-svg-icons/faChevronCircleDown"; +export { definition as faChevronCircleLeft } from "@fortawesome/free-solid-svg-icons/faChevronCircleLeft"; +export { definition as faChevronCircleRight } from "@fortawesome/free-solid-svg-icons/faChevronCircleRight"; +export { definition as faChevronCircleUp } from "@fortawesome/free-solid-svg-icons/faChevronCircleUp"; +export { definition as faChevronDown } from "@fortawesome/free-solid-svg-icons/faChevronDown"; +export { definition as faChevronLeft } from "@fortawesome/free-solid-svg-icons/faChevronLeft"; +export { definition as faChevronRight } from "@fortawesome/free-solid-svg-icons/faChevronRight"; +export { definition as faChevronUp } from "@fortawesome/free-solid-svg-icons/faChevronUp"; +export { definition as faChild } from "@fortawesome/free-solid-svg-icons/faChild"; +export { definition as faChildCombatant } from "@fortawesome/free-solid-svg-icons/faChildCombatant"; +export { definition as faChildDress } from "@fortawesome/free-solid-svg-icons/faChildDress"; +export { definition as faChildReaching } from "@fortawesome/free-solid-svg-icons/faChildReaching"; +export { definition as faChildRifle } from "@fortawesome/free-solid-svg-icons/faChildRifle"; +export { definition as faChildren } from "@fortawesome/free-solid-svg-icons/faChildren"; +export { definition as faChurch } from "@fortawesome/free-solid-svg-icons/faChurch"; +export { definition as faCircle } from "@fortawesome/free-solid-svg-icons/faCircle"; +export { definition as faCircleArrowDown } from "@fortawesome/free-solid-svg-icons/faCircleArrowDown"; +export { definition as faCircleArrowLeft } from "@fortawesome/free-solid-svg-icons/faCircleArrowLeft"; +export { definition as faCircleArrowRight } from "@fortawesome/free-solid-svg-icons/faCircleArrowRight"; +export { definition as faCircleArrowUp } from "@fortawesome/free-solid-svg-icons/faCircleArrowUp"; +export { definition as faCircleCheck } from "@fortawesome/free-solid-svg-icons/faCircleCheck"; +export { definition as faCircleChevronDown } from "@fortawesome/free-solid-svg-icons/faCircleChevronDown"; +export { definition as faCircleChevronLeft } from "@fortawesome/free-solid-svg-icons/faCircleChevronLeft"; +export { definition as faCircleChevronRight } from "@fortawesome/free-solid-svg-icons/faCircleChevronRight"; +export { definition as faCircleChevronUp } from "@fortawesome/free-solid-svg-icons/faCircleChevronUp"; +export { definition as faCircleDollarToSlot } from "@fortawesome/free-solid-svg-icons/faCircleDollarToSlot"; +export { definition as faCircleDot } from "@fortawesome/free-solid-svg-icons/faCircleDot"; +export { definition as faCircleDown } from "@fortawesome/free-solid-svg-icons/faCircleDown"; +export { definition as faCircleExclamation } from "@fortawesome/free-solid-svg-icons/faCircleExclamation"; +export { definition as faCircleH } from "@fortawesome/free-solid-svg-icons/faCircleH"; +export { definition as faCircleHalfStroke } from "@fortawesome/free-solid-svg-icons/faCircleHalfStroke"; +export { definition as faCircleInfo } from "@fortawesome/free-solid-svg-icons/faCircleInfo"; +export { definition as faCircleLeft } from "@fortawesome/free-solid-svg-icons/faCircleLeft"; +export { definition as faCircleMinus } from "@fortawesome/free-solid-svg-icons/faCircleMinus"; +export { definition as faCircleNodes } from "@fortawesome/free-solid-svg-icons/faCircleNodes"; +export { definition as faCircleNotch } from "@fortawesome/free-solid-svg-icons/faCircleNotch"; +export { definition as faCirclePause } from "@fortawesome/free-solid-svg-icons/faCirclePause"; +export { definition as faCirclePlay } from "@fortawesome/free-solid-svg-icons/faCirclePlay"; +export { definition as faCirclePlus } from "@fortawesome/free-solid-svg-icons/faCirclePlus"; +export { definition as faCircleQuestion } from "@fortawesome/free-solid-svg-icons/faCircleQuestion"; +export { definition as faCircleRadiation } from "@fortawesome/free-solid-svg-icons/faCircleRadiation"; +export { definition as faCircleRight } from "@fortawesome/free-solid-svg-icons/faCircleRight"; +export { definition as faCircleStop } from "@fortawesome/free-solid-svg-icons/faCircleStop"; +export { definition as faCircleUp } from "@fortawesome/free-solid-svg-icons/faCircleUp"; +export { definition as faCircleUser } from "@fortawesome/free-solid-svg-icons/faCircleUser"; +export { definition as faCircleXmark } from "@fortawesome/free-solid-svg-icons/faCircleXmark"; +export { definition as faCity } from "@fortawesome/free-solid-svg-icons/faCity"; +export { definition as faClapperboard } from "@fortawesome/free-solid-svg-icons/faClapperboard"; +export { definition as faClinicMedical } from "@fortawesome/free-solid-svg-icons/faClinicMedical"; +export { definition as faClipboard } from "@fortawesome/free-solid-svg-icons/faClipboard"; +export { definition as faClipboardCheck } from "@fortawesome/free-solid-svg-icons/faClipboardCheck"; +export { definition as faClipboardList } from "@fortawesome/free-solid-svg-icons/faClipboardList"; +export { definition as faClipboardQuestion } from "@fortawesome/free-solid-svg-icons/faClipboardQuestion"; +export { definition as faClipboardUser } from "@fortawesome/free-solid-svg-icons/faClipboardUser"; +export { definition as faClock } from "@fortawesome/free-solid-svg-icons/faClock"; +export { definition as faClockFour } from "@fortawesome/free-solid-svg-icons/faClockFour"; +export { definition as faClockRotateLeft } from "@fortawesome/free-solid-svg-icons/faClockRotateLeft"; +export { definition as faClone } from "@fortawesome/free-solid-svg-icons/faClone"; +export { definition as faClose } from "@fortawesome/free-solid-svg-icons/faClose"; +export { definition as faClosedCaptioning } from "@fortawesome/free-solid-svg-icons/faClosedCaptioning"; +export { definition as faCloud } from "@fortawesome/free-solid-svg-icons/faCloud"; +export { definition as faCloudArrowDown } from "@fortawesome/free-solid-svg-icons/faCloudArrowDown"; +export { definition as faCloudArrowUp } from "@fortawesome/free-solid-svg-icons/faCloudArrowUp"; +export { definition as faCloudBolt } from "@fortawesome/free-solid-svg-icons/faCloudBolt"; +export { definition as faCloudDownload } from "@fortawesome/free-solid-svg-icons/faCloudDownload"; +export { definition as faCloudDownloadAlt } from "@fortawesome/free-solid-svg-icons/faCloudDownloadAlt"; +export { definition as faCloudMeatball } from "@fortawesome/free-solid-svg-icons/faCloudMeatball"; +export { definition as faCloudMoon } from "@fortawesome/free-solid-svg-icons/faCloudMoon"; +export { definition as faCloudMoonRain } from "@fortawesome/free-solid-svg-icons/faCloudMoonRain"; +export { definition as faCloudRain } from "@fortawesome/free-solid-svg-icons/faCloudRain"; +export { definition as faCloudShowersHeavy } from "@fortawesome/free-solid-svg-icons/faCloudShowersHeavy"; +export { definition as faCloudShowersWater } from "@fortawesome/free-solid-svg-icons/faCloudShowersWater"; +export { definition as faCloudSun } from "@fortawesome/free-solid-svg-icons/faCloudSun"; +export { definition as faCloudSunRain } from "@fortawesome/free-solid-svg-icons/faCloudSunRain"; +export { definition as faCloudUpload } from "@fortawesome/free-solid-svg-icons/faCloudUpload"; +export { definition as faCloudUploadAlt } from "@fortawesome/free-solid-svg-icons/faCloudUploadAlt"; +export { definition as faClover } from "@fortawesome/free-solid-svg-icons/faClover"; +export { definition as faCny } from "@fortawesome/free-solid-svg-icons/faCny"; +export { definition as faCocktail } from "@fortawesome/free-solid-svg-icons/faCocktail"; +export { definition as faCode } from "@fortawesome/free-solid-svg-icons/faCode"; +export { definition as faCodeBranch } from "@fortawesome/free-solid-svg-icons/faCodeBranch"; +export { definition as faCodeCommit } from "@fortawesome/free-solid-svg-icons/faCodeCommit"; +export { definition as faCodeCompare } from "@fortawesome/free-solid-svg-icons/faCodeCompare"; +export { definition as faCodeFork } from "@fortawesome/free-solid-svg-icons/faCodeFork"; +export { definition as faCodeMerge } from "@fortawesome/free-solid-svg-icons/faCodeMerge"; +export { definition as faCodePullRequest } from "@fortawesome/free-solid-svg-icons/faCodePullRequest"; +export { definition as faCoffee } from "@fortawesome/free-solid-svg-icons/faCoffee"; +export { definition as faCog } from "@fortawesome/free-solid-svg-icons/faCog"; +export { definition as faCogs } from "@fortawesome/free-solid-svg-icons/faCogs"; +export { definition as faCoins } from "@fortawesome/free-solid-svg-icons/faCoins"; +export { definition as faColonSign } from "@fortawesome/free-solid-svg-icons/faColonSign"; +export { definition as faColumns } from "@fortawesome/free-solid-svg-icons/faColumns"; +export { definition as faComment } from "@fortawesome/free-solid-svg-icons/faComment"; +export { definition as faCommentAlt } from "@fortawesome/free-solid-svg-icons/faCommentAlt"; +export { definition as faCommentDollar } from "@fortawesome/free-solid-svg-icons/faCommentDollar"; +export { definition as faCommentDots } from "@fortawesome/free-solid-svg-icons/faCommentDots"; +export { definition as faCommentMedical } from "@fortawesome/free-solid-svg-icons/faCommentMedical"; +export { definition as faCommentNodes } from "@fortawesome/free-solid-svg-icons/faCommentNodes"; +export { definition as faCommentSlash } from "@fortawesome/free-solid-svg-icons/faCommentSlash"; +export { definition as faCommentSms } from "@fortawesome/free-solid-svg-icons/faCommentSms"; +export { definition as faCommenting } from "@fortawesome/free-solid-svg-icons/faCommenting"; +export { definition as faComments } from "@fortawesome/free-solid-svg-icons/faComments"; +export { definition as faCommentsDollar } from "@fortawesome/free-solid-svg-icons/faCommentsDollar"; +export { definition as faCompactDisc } from "@fortawesome/free-solid-svg-icons/faCompactDisc"; +export { definition as faCompass } from "@fortawesome/free-solid-svg-icons/faCompass"; +export { definition as faCompassDrafting } from "@fortawesome/free-solid-svg-icons/faCompassDrafting"; +export { definition as faCompress } from "@fortawesome/free-solid-svg-icons/faCompress"; +export { definition as faCompressAlt } from "@fortawesome/free-solid-svg-icons/faCompressAlt"; +export { definition as faCompressArrowsAlt } from "@fortawesome/free-solid-svg-icons/faCompressArrowsAlt"; +export { definition as faComputer } from "@fortawesome/free-solid-svg-icons/faComputer"; +export { definition as faComputerMouse } from "@fortawesome/free-solid-svg-icons/faComputerMouse"; +export { definition as faConciergeBell } from "@fortawesome/free-solid-svg-icons/faConciergeBell"; +export { definition as faContactBook } from "@fortawesome/free-solid-svg-icons/faContactBook"; +export { definition as faContactCard } from "@fortawesome/free-solid-svg-icons/faContactCard"; +export { definition as faCookie } from "@fortawesome/free-solid-svg-icons/faCookie"; +export { definition as faCookieBite } from "@fortawesome/free-solid-svg-icons/faCookieBite"; +export { definition as faCopy } from "@fortawesome/free-solid-svg-icons/faCopy"; +export { definition as faCopyright } from "@fortawesome/free-solid-svg-icons/faCopyright"; +export { definition as faCouch } from "@fortawesome/free-solid-svg-icons/faCouch"; +export { definition as faCow } from "@fortawesome/free-solid-svg-icons/faCow"; +export { definition as faCreditCard } from "@fortawesome/free-solid-svg-icons/faCreditCard"; +export { definition as faCreditCardAlt } from "@fortawesome/free-solid-svg-icons/faCreditCardAlt"; +export { definition as faCrop } from "@fortawesome/free-solid-svg-icons/faCrop"; +export { definition as faCropAlt } from "@fortawesome/free-solid-svg-icons/faCropAlt"; +export { definition as faCropSimple } from "@fortawesome/free-solid-svg-icons/faCropSimple"; +export { definition as faCross } from "@fortawesome/free-solid-svg-icons/faCross"; +export { definition as faCrosshairs } from "@fortawesome/free-solid-svg-icons/faCrosshairs"; +export { definition as faCrow } from "@fortawesome/free-solid-svg-icons/faCrow"; +export { definition as faCrown } from "@fortawesome/free-solid-svg-icons/faCrown"; +export { definition as faCrutch } from "@fortawesome/free-solid-svg-icons/faCrutch"; +export { definition as faCruzeiroSign } from "@fortawesome/free-solid-svg-icons/faCruzeiroSign"; +export { definition as faCube } from "@fortawesome/free-solid-svg-icons/faCube"; +export { definition as faCubes } from "@fortawesome/free-solid-svg-icons/faCubes"; +export { definition as faCubesStacked } from "@fortawesome/free-solid-svg-icons/faCubesStacked"; +export { definition as faCut } from "@fortawesome/free-solid-svg-icons/faCut"; +export { definition as faCutlery } from "@fortawesome/free-solid-svg-icons/faCutlery"; +export { definition as faD } from "@fortawesome/free-solid-svg-icons/faD"; +export { definition as faDashboard } from "@fortawesome/free-solid-svg-icons/faDashboard"; +export { definition as faDatabase } from "@fortawesome/free-solid-svg-icons/faDatabase"; +export { definition as faDeaf } from "@fortawesome/free-solid-svg-icons/faDeaf"; +export { definition as faDeafness } from "@fortawesome/free-solid-svg-icons/faDeafness"; +export { definition as faDedent } from "@fortawesome/free-solid-svg-icons/faDedent"; +export { definition as faDeleteLeft } from "@fortawesome/free-solid-svg-icons/faDeleteLeft"; +export { definition as faDemocrat } from "@fortawesome/free-solid-svg-icons/faDemocrat"; +export { definition as faDesktop } from "@fortawesome/free-solid-svg-icons/faDesktop"; +export { definition as faDesktopAlt } from "@fortawesome/free-solid-svg-icons/faDesktopAlt"; +export { definition as faDharmachakra } from "@fortawesome/free-solid-svg-icons/faDharmachakra"; +export { definition as faDiagnoses } from "@fortawesome/free-solid-svg-icons/faDiagnoses"; +export { definition as faDiagramNext } from "@fortawesome/free-solid-svg-icons/faDiagramNext"; +export { definition as faDiagramPredecessor } from "@fortawesome/free-solid-svg-icons/faDiagramPredecessor"; +export { definition as faDiagramProject } from "@fortawesome/free-solid-svg-icons/faDiagramProject"; +export { definition as faDiagramSuccessor } from "@fortawesome/free-solid-svg-icons/faDiagramSuccessor"; +export { definition as faDiamond } from "@fortawesome/free-solid-svg-icons/faDiamond"; +export { definition as faDiamondTurnRight } from "@fortawesome/free-solid-svg-icons/faDiamondTurnRight"; +export { definition as faDice } from "@fortawesome/free-solid-svg-icons/faDice"; +export { definition as faDiceD20 } from "@fortawesome/free-solid-svg-icons/faDiceD20"; +export { definition as faDiceD6 } from "@fortawesome/free-solid-svg-icons/faDiceD6"; +export { definition as faDiceFive } from "@fortawesome/free-solid-svg-icons/faDiceFive"; +export { definition as faDiceFour } from "@fortawesome/free-solid-svg-icons/faDiceFour"; +export { definition as faDiceOne } from "@fortawesome/free-solid-svg-icons/faDiceOne"; +export { definition as faDiceSix } from "@fortawesome/free-solid-svg-icons/faDiceSix"; +export { definition as faDiceThree } from "@fortawesome/free-solid-svg-icons/faDiceThree"; +export { definition as faDiceTwo } from "@fortawesome/free-solid-svg-icons/faDiceTwo"; +export { definition as faDigging } from "@fortawesome/free-solid-svg-icons/faDigging"; +export { definition as faDigitalTachograph } from "@fortawesome/free-solid-svg-icons/faDigitalTachograph"; +export { definition as faDirections } from "@fortawesome/free-solid-svg-icons/faDirections"; +export { definition as faDisease } from "@fortawesome/free-solid-svg-icons/faDisease"; +export { definition as faDisplay } from "@fortawesome/free-solid-svg-icons/faDisplay"; +export { definition as faDivide } from "@fortawesome/free-solid-svg-icons/faDivide"; +export { definition as faDizzy } from "@fortawesome/free-solid-svg-icons/faDizzy"; +export { definition as faDna } from "@fortawesome/free-solid-svg-icons/faDna"; +export { definition as faDog } from "@fortawesome/free-solid-svg-icons/faDog"; +export { definition as faDollar } from "@fortawesome/free-solid-svg-icons/faDollar"; +export { definition as faDollarSign } from "@fortawesome/free-solid-svg-icons/faDollarSign"; +export { definition as faDolly } from "@fortawesome/free-solid-svg-icons/faDolly"; +export { definition as faDollyBox } from "@fortawesome/free-solid-svg-icons/faDollyBox"; +export { definition as faDollyFlatbed } from "@fortawesome/free-solid-svg-icons/faDollyFlatbed"; +export { definition as faDonate } from "@fortawesome/free-solid-svg-icons/faDonate"; +export { definition as faDongSign } from "@fortawesome/free-solid-svg-icons/faDongSign"; +export { definition as faDoorClosed } from "@fortawesome/free-solid-svg-icons/faDoorClosed"; +export { definition as faDoorOpen } from "@fortawesome/free-solid-svg-icons/faDoorOpen"; +export { definition as faDotCircle } from "@fortawesome/free-solid-svg-icons/faDotCircle"; +export { definition as faDove } from "@fortawesome/free-solid-svg-icons/faDove"; +export { definition as faDownLeftAndUpRightToCenter } from "@fortawesome/free-solid-svg-icons/faDownLeftAndUpRightToCenter"; +export { definition as faDownLong } from "@fortawesome/free-solid-svg-icons/faDownLong"; +export { definition as faDownload } from "@fortawesome/free-solid-svg-icons/faDownload"; +export { definition as faDraftingCompass } from "@fortawesome/free-solid-svg-icons/faDraftingCompass"; +export { definition as faDragon } from "@fortawesome/free-solid-svg-icons/faDragon"; +export { definition as faDrawPolygon } from "@fortawesome/free-solid-svg-icons/faDrawPolygon"; +export { definition as faDriversLicense } from "@fortawesome/free-solid-svg-icons/faDriversLicense"; +export { definition as faDroplet } from "@fortawesome/free-solid-svg-icons/faDroplet"; +export { definition as faDropletSlash } from "@fortawesome/free-solid-svg-icons/faDropletSlash"; +export { definition as faDrum } from "@fortawesome/free-solid-svg-icons/faDrum"; +export { definition as faDrumSteelpan } from "@fortawesome/free-solid-svg-icons/faDrumSteelpan"; +export { definition as faDrumstickBite } from "@fortawesome/free-solid-svg-icons/faDrumstickBite"; +export { definition as faDumbbell } from "@fortawesome/free-solid-svg-icons/faDumbbell"; +export { definition as faDumpster } from "@fortawesome/free-solid-svg-icons/faDumpster"; +export { definition as faDumpsterFire } from "@fortawesome/free-solid-svg-icons/faDumpsterFire"; +export { definition as faDungeon } from "@fortawesome/free-solid-svg-icons/faDungeon"; +export { definition as faE } from "@fortawesome/free-solid-svg-icons/faE"; +export { definition as faEarDeaf } from "@fortawesome/free-solid-svg-icons/faEarDeaf"; +export { definition as faEarListen } from "@fortawesome/free-solid-svg-icons/faEarListen"; +export { definition as faEarth } from "@fortawesome/free-solid-svg-icons/faEarth"; +export { definition as faEarthAfrica } from "@fortawesome/free-solid-svg-icons/faEarthAfrica"; +export { definition as faEarthAmerica } from "@fortawesome/free-solid-svg-icons/faEarthAmerica"; +export { definition as faEarthAmericas } from "@fortawesome/free-solid-svg-icons/faEarthAmericas"; +export { definition as faEarthAsia } from "@fortawesome/free-solid-svg-icons/faEarthAsia"; +export { definition as faEarthEurope } from "@fortawesome/free-solid-svg-icons/faEarthEurope"; +export { definition as faEarthOceania } from "@fortawesome/free-solid-svg-icons/faEarthOceania"; +export { definition as faEdit } from "@fortawesome/free-solid-svg-icons/faEdit"; +export { definition as faEgg } from "@fortawesome/free-solid-svg-icons/faEgg"; +export { definition as faEject } from "@fortawesome/free-solid-svg-icons/faEject"; +export { definition as faElevator } from "@fortawesome/free-solid-svg-icons/faElevator"; +export { definition as faEllipsis } from "@fortawesome/free-solid-svg-icons/faEllipsis"; +export { definition as faEllipsisH } from "@fortawesome/free-solid-svg-icons/faEllipsisH"; +export { definition as faEllipsisV } from "@fortawesome/free-solid-svg-icons/faEllipsisV"; +export { definition as faEllipsisVertical } from "@fortawesome/free-solid-svg-icons/faEllipsisVertical"; +export { definition as faEnvelope } from "@fortawesome/free-solid-svg-icons/faEnvelope"; +export { definition as faEnvelopeCircleCheck } from "@fortawesome/free-solid-svg-icons/faEnvelopeCircleCheck"; +export { definition as faEnvelopeOpen } from "@fortawesome/free-solid-svg-icons/faEnvelopeOpen"; +export { definition as faEnvelopeOpenText } from "@fortawesome/free-solid-svg-icons/faEnvelopeOpenText"; +export { definition as faEnvelopeSquare } from "@fortawesome/free-solid-svg-icons/faEnvelopeSquare"; +export { definition as faEnvelopesBulk } from "@fortawesome/free-solid-svg-icons/faEnvelopesBulk"; +export { definition as faEquals } from "@fortawesome/free-solid-svg-icons/faEquals"; +export { definition as faEraser } from "@fortawesome/free-solid-svg-icons/faEraser"; +export { definition as faEthernet } from "@fortawesome/free-solid-svg-icons/faEthernet"; +export { definition as faEur } from "@fortawesome/free-solid-svg-icons/faEur"; +export { definition as faEuro } from "@fortawesome/free-solid-svg-icons/faEuro"; +export { definition as faEuroSign } from "@fortawesome/free-solid-svg-icons/faEuroSign"; +export { definition as faExchange } from "@fortawesome/free-solid-svg-icons/faExchange"; +export { definition as faExchangeAlt } from "@fortawesome/free-solid-svg-icons/faExchangeAlt"; +export { definition as faExclamation } from "@fortawesome/free-solid-svg-icons/faExclamation"; +export { definition as faExclamationCircle } from "@fortawesome/free-solid-svg-icons/faExclamationCircle"; +export { definition as faExclamationTriangle } from "@fortawesome/free-solid-svg-icons/faExclamationTriangle"; +export { definition as faExpand } from "@fortawesome/free-solid-svg-icons/faExpand"; +export { definition as faExpandAlt } from "@fortawesome/free-solid-svg-icons/faExpandAlt"; +export { definition as faExpandArrowsAlt } from "@fortawesome/free-solid-svg-icons/faExpandArrowsAlt"; +export { definition as faExplosion } from "@fortawesome/free-solid-svg-icons/faExplosion"; +export { definition as faExternalLink } from "@fortawesome/free-solid-svg-icons/faExternalLink"; +export { definition as faExternalLinkAlt } from "@fortawesome/free-solid-svg-icons/faExternalLinkAlt"; +export { definition as faExternalLinkSquare } from "@fortawesome/free-solid-svg-icons/faExternalLinkSquare"; +export { definition as faExternalLinkSquareAlt } from "@fortawesome/free-solid-svg-icons/faExternalLinkSquareAlt"; +export { definition as faEye } from "@fortawesome/free-solid-svg-icons/faEye"; +export { definition as faEyeDropper } from "@fortawesome/free-solid-svg-icons/faEyeDropper"; +export { definition as faEyeDropperEmpty } from "@fortawesome/free-solid-svg-icons/faEyeDropperEmpty"; +export { definition as faEyeLowVision } from "@fortawesome/free-solid-svg-icons/faEyeLowVision"; +export { definition as faEyeSlash } from "@fortawesome/free-solid-svg-icons/faEyeSlash"; +export { definition as faF } from "@fortawesome/free-solid-svg-icons/faF"; +export { definition as faFaceAngry } from "@fortawesome/free-solid-svg-icons/faFaceAngry"; +export { definition as faFaceDizzy } from "@fortawesome/free-solid-svg-icons/faFaceDizzy"; +export { definition as faFaceFlushed } from "@fortawesome/free-solid-svg-icons/faFaceFlushed"; +export { definition as faFaceFrown } from "@fortawesome/free-solid-svg-icons/faFaceFrown"; +export { definition as faFaceFrownOpen } from "@fortawesome/free-solid-svg-icons/faFaceFrownOpen"; +export { definition as faFaceGrimace } from "@fortawesome/free-solid-svg-icons/faFaceGrimace"; +export { definition as faFaceGrin } from "@fortawesome/free-solid-svg-icons/faFaceGrin"; +export { definition as faFaceGrinBeam } from "@fortawesome/free-solid-svg-icons/faFaceGrinBeam"; +export { definition as faFaceGrinBeamSweat } from "@fortawesome/free-solid-svg-icons/faFaceGrinBeamSweat"; +export { definition as faFaceGrinHearts } from "@fortawesome/free-solid-svg-icons/faFaceGrinHearts"; +export { definition as faFaceGrinSquint } from "@fortawesome/free-solid-svg-icons/faFaceGrinSquint"; +export { definition as faFaceGrinSquintTears } from "@fortawesome/free-solid-svg-icons/faFaceGrinSquintTears"; +export { definition as faFaceGrinStars } from "@fortawesome/free-solid-svg-icons/faFaceGrinStars"; +export { definition as faFaceGrinTears } from "@fortawesome/free-solid-svg-icons/faFaceGrinTears"; +export { definition as faFaceGrinTongue } from "@fortawesome/free-solid-svg-icons/faFaceGrinTongue"; +export { definition as faFaceGrinTongueSquint } from "@fortawesome/free-solid-svg-icons/faFaceGrinTongueSquint"; +export { definition as faFaceGrinTongueWink } from "@fortawesome/free-solid-svg-icons/faFaceGrinTongueWink"; +export { definition as faFaceGrinWide } from "@fortawesome/free-solid-svg-icons/faFaceGrinWide"; +export { definition as faFaceGrinWink } from "@fortawesome/free-solid-svg-icons/faFaceGrinWink"; +export { definition as faFaceKiss } from "@fortawesome/free-solid-svg-icons/faFaceKiss"; +export { definition as faFaceKissBeam } from "@fortawesome/free-solid-svg-icons/faFaceKissBeam"; +export { definition as faFaceKissWinkHeart } from "@fortawesome/free-solid-svg-icons/faFaceKissWinkHeart"; +export { definition as faFaceLaugh } from "@fortawesome/free-solid-svg-icons/faFaceLaugh"; +export { definition as faFaceLaughBeam } from "@fortawesome/free-solid-svg-icons/faFaceLaughBeam"; +export { definition as faFaceLaughSquint } from "@fortawesome/free-solid-svg-icons/faFaceLaughSquint"; +export { definition as faFaceLaughWink } from "@fortawesome/free-solid-svg-icons/faFaceLaughWink"; +export { definition as faFaceMeh } from "@fortawesome/free-solid-svg-icons/faFaceMeh"; +export { definition as faFaceMehBlank } from "@fortawesome/free-solid-svg-icons/faFaceMehBlank"; +export { definition as faFaceRollingEyes } from "@fortawesome/free-solid-svg-icons/faFaceRollingEyes"; +export { definition as faFaceSadCry } from "@fortawesome/free-solid-svg-icons/faFaceSadCry"; +export { definition as faFaceSadTear } from "@fortawesome/free-solid-svg-icons/faFaceSadTear"; +export { definition as faFaceSmile } from "@fortawesome/free-solid-svg-icons/faFaceSmile"; +export { definition as faFaceSmileBeam } from "@fortawesome/free-solid-svg-icons/faFaceSmileBeam"; +export { definition as faFaceSmileWink } from "@fortawesome/free-solid-svg-icons/faFaceSmileWink"; +export { definition as faFaceSurprise } from "@fortawesome/free-solid-svg-icons/faFaceSurprise"; +export { definition as faFaceTired } from "@fortawesome/free-solid-svg-icons/faFaceTired"; +export { definition as faFan } from "@fortawesome/free-solid-svg-icons/faFan"; +export { definition as faFastBackward } from "@fortawesome/free-solid-svg-icons/faFastBackward"; +export { definition as faFastForward } from "@fortawesome/free-solid-svg-icons/faFastForward"; +export { definition as faFaucet } from "@fortawesome/free-solid-svg-icons/faFaucet"; +export { definition as faFaucetDrip } from "@fortawesome/free-solid-svg-icons/faFaucetDrip"; +export { definition as faFax } from "@fortawesome/free-solid-svg-icons/faFax"; +export { definition as faFeather } from "@fortawesome/free-solid-svg-icons/faFeather"; +export { definition as faFeatherAlt } from "@fortawesome/free-solid-svg-icons/faFeatherAlt"; +export { definition as faFeatherPointed } from "@fortawesome/free-solid-svg-icons/faFeatherPointed"; +export { definition as faFeed } from "@fortawesome/free-solid-svg-icons/faFeed"; +export { definition as faFemale } from "@fortawesome/free-solid-svg-icons/faFemale"; +export { definition as faFerry } from "@fortawesome/free-solid-svg-icons/faFerry"; +export { definition as faFighterJet } from "@fortawesome/free-solid-svg-icons/faFighterJet"; +export { definition as faFile } from "@fortawesome/free-solid-svg-icons/faFile"; +export { definition as faFileAlt } from "@fortawesome/free-solid-svg-icons/faFileAlt"; +export { definition as faFileArchive } from "@fortawesome/free-solid-svg-icons/faFileArchive"; +export { definition as faFileArrowDown } from "@fortawesome/free-solid-svg-icons/faFileArrowDown"; +export { definition as faFileArrowUp } from "@fortawesome/free-solid-svg-icons/faFileArrowUp"; +export { definition as faFileAudio } from "@fortawesome/free-solid-svg-icons/faFileAudio"; +export { definition as faFileCircleCheck } from "@fortawesome/free-solid-svg-icons/faFileCircleCheck"; +export { definition as faFileCircleExclamation } from "@fortawesome/free-solid-svg-icons/faFileCircleExclamation"; +export { definition as faFileCircleMinus } from "@fortawesome/free-solid-svg-icons/faFileCircleMinus"; +export { definition as faFileCirclePlus } from "@fortawesome/free-solid-svg-icons/faFileCirclePlus"; +export { definition as faFileCircleQuestion } from "@fortawesome/free-solid-svg-icons/faFileCircleQuestion"; +export { definition as faFileCircleXmark } from "@fortawesome/free-solid-svg-icons/faFileCircleXmark"; +export { definition as faFileClipboard } from "@fortawesome/free-solid-svg-icons/faFileClipboard"; +export { definition as faFileCode } from "@fortawesome/free-solid-svg-icons/faFileCode"; +export { definition as faFileContract } from "@fortawesome/free-solid-svg-icons/faFileContract"; +export { definition as faFileCsv } from "@fortawesome/free-solid-svg-icons/faFileCsv"; +export { definition as faFileDownload } from "@fortawesome/free-solid-svg-icons/faFileDownload"; +export { definition as faFileEdit } from "@fortawesome/free-solid-svg-icons/faFileEdit"; +export { definition as faFileExcel } from "@fortawesome/free-solid-svg-icons/faFileExcel"; +export { definition as faFileExport } from "@fortawesome/free-solid-svg-icons/faFileExport"; +export { definition as faFileFragment } from "@fortawesome/free-solid-svg-icons/faFileFragment"; +export { definition as faFileHalfDashed } from "@fortawesome/free-solid-svg-icons/faFileHalfDashed"; +export { definition as faFileImage } from "@fortawesome/free-solid-svg-icons/faFileImage"; +export { definition as faFileImport } from "@fortawesome/free-solid-svg-icons/faFileImport"; +export { definition as faFileInvoice } from "@fortawesome/free-solid-svg-icons/faFileInvoice"; +export { definition as faFileInvoiceDollar } from "@fortawesome/free-solid-svg-icons/faFileInvoiceDollar"; +export { definition as faFileLines } from "@fortawesome/free-solid-svg-icons/faFileLines"; +export { definition as faFileMedical } from "@fortawesome/free-solid-svg-icons/faFileMedical"; +export { definition as faFileMedicalAlt } from "@fortawesome/free-solid-svg-icons/faFileMedicalAlt"; +export { definition as faFilePdf } from "@fortawesome/free-solid-svg-icons/faFilePdf"; +export { definition as faFilePen } from "@fortawesome/free-solid-svg-icons/faFilePen"; +export { definition as faFilePowerpoint } from "@fortawesome/free-solid-svg-icons/faFilePowerpoint"; +export { definition as faFilePrescription } from "@fortawesome/free-solid-svg-icons/faFilePrescription"; +export { definition as faFileShield } from "@fortawesome/free-solid-svg-icons/faFileShield"; +export { definition as faFileSignature } from "@fortawesome/free-solid-svg-icons/faFileSignature"; +export { definition as faFileText } from "@fortawesome/free-solid-svg-icons/faFileText"; +export { definition as faFileUpload } from "@fortawesome/free-solid-svg-icons/faFileUpload"; +export { definition as faFileVideo } from "@fortawesome/free-solid-svg-icons/faFileVideo"; +export { definition as faFileWaveform } from "@fortawesome/free-solid-svg-icons/faFileWaveform"; +export { definition as faFileWord } from "@fortawesome/free-solid-svg-icons/faFileWord"; +export { definition as faFileZipper } from "@fortawesome/free-solid-svg-icons/faFileZipper"; +export { definition as faFill } from "@fortawesome/free-solid-svg-icons/faFill"; +export { definition as faFillDrip } from "@fortawesome/free-solid-svg-icons/faFillDrip"; +export { definition as faFilm } from "@fortawesome/free-solid-svg-icons/faFilm"; +export { definition as faFilter } from "@fortawesome/free-solid-svg-icons/faFilter"; +export { definition as faFilterCircleDollar } from "@fortawesome/free-solid-svg-icons/faFilterCircleDollar"; +export { definition as faFilterCircleXmark } from "@fortawesome/free-solid-svg-icons/faFilterCircleXmark"; +export { definition as faFingerprint } from "@fortawesome/free-solid-svg-icons/faFingerprint"; +export { definition as faFire } from "@fortawesome/free-solid-svg-icons/faFire"; +export { definition as faFireAlt } from "@fortawesome/free-solid-svg-icons/faFireAlt"; +export { definition as faFireBurner } from "@fortawesome/free-solid-svg-icons/faFireBurner"; +export { definition as faFireExtinguisher } from "@fortawesome/free-solid-svg-icons/faFireExtinguisher"; +export { definition as faFireFlameCurved } from "@fortawesome/free-solid-svg-icons/faFireFlameCurved"; +export { definition as faFireFlameSimple } from "@fortawesome/free-solid-svg-icons/faFireFlameSimple"; +export { definition as faFirstAid } from "@fortawesome/free-solid-svg-icons/faFirstAid"; +export { definition as faFish } from "@fortawesome/free-solid-svg-icons/faFish"; +export { definition as faFishFins } from "@fortawesome/free-solid-svg-icons/faFishFins"; +export { definition as faFistRaised } from "@fortawesome/free-solid-svg-icons/faFistRaised"; +export { definition as faFlag } from "@fortawesome/free-solid-svg-icons/faFlag"; +export { definition as faFlagCheckered } from "@fortawesome/free-solid-svg-icons/faFlagCheckered"; +export { definition as faFlagUsa } from "@fortawesome/free-solid-svg-icons/faFlagUsa"; +export { definition as faFlask } from "@fortawesome/free-solid-svg-icons/faFlask"; +export { definition as faFlaskVial } from "@fortawesome/free-solid-svg-icons/faFlaskVial"; +export { definition as faFloppyDisk } from "@fortawesome/free-solid-svg-icons/faFloppyDisk"; +export { definition as faFlorinSign } from "@fortawesome/free-solid-svg-icons/faFlorinSign"; +export { definition as faFlushed } from "@fortawesome/free-solid-svg-icons/faFlushed"; +export { definition as faFolder } from "@fortawesome/free-solid-svg-icons/faFolder"; +export { definition as faFolderBlank } from "@fortawesome/free-solid-svg-icons/faFolderBlank"; +export { definition as faFolderClosed } from "@fortawesome/free-solid-svg-icons/faFolderClosed"; +export { definition as faFolderMinus } from "@fortawesome/free-solid-svg-icons/faFolderMinus"; +export { definition as faFolderOpen } from "@fortawesome/free-solid-svg-icons/faFolderOpen"; +export { definition as faFolderPlus } from "@fortawesome/free-solid-svg-icons/faFolderPlus"; +export { definition as faFolderTree } from "@fortawesome/free-solid-svg-icons/faFolderTree"; +export { definition as faFont } from "@fortawesome/free-solid-svg-icons/faFont"; +export { definition as faFontAwesome } from "@fortawesome/free-solid-svg-icons/faFontAwesome"; +export { definition as faFontAwesomeFlag } from "@fortawesome/free-solid-svg-icons/faFontAwesomeFlag"; +export { definition as faFontAwesomeLogoFull } from "@fortawesome/free-solid-svg-icons/faFontAwesomeLogoFull"; +export { definition as faFootball } from "@fortawesome/free-solid-svg-icons/faFootball"; +export { definition as faFootballBall } from "@fortawesome/free-solid-svg-icons/faFootballBall"; +export { definition as faForward } from "@fortawesome/free-solid-svg-icons/faForward"; +export { definition as faForwardFast } from "@fortawesome/free-solid-svg-icons/faForwardFast"; +export { definition as faForwardStep } from "@fortawesome/free-solid-svg-icons/faForwardStep"; +export { definition as faFrancSign } from "@fortawesome/free-solid-svg-icons/faFrancSign"; +export { definition as faFrog } from "@fortawesome/free-solid-svg-icons/faFrog"; +export { definition as faFrown } from "@fortawesome/free-solid-svg-icons/faFrown"; +export { definition as faFrownOpen } from "@fortawesome/free-solid-svg-icons/faFrownOpen"; +export { definition as faFunnelDollar } from "@fortawesome/free-solid-svg-icons/faFunnelDollar"; +export { definition as faFutbol } from "@fortawesome/free-solid-svg-icons/faFutbol"; +export { definition as faFutbolBall } from "@fortawesome/free-solid-svg-icons/faFutbolBall"; +export { definition as faG } from "@fortawesome/free-solid-svg-icons/faG"; +export { definition as faGamepad } from "@fortawesome/free-solid-svg-icons/faGamepad"; +export { definition as faGasPump } from "@fortawesome/free-solid-svg-icons/faGasPump"; +export { definition as faGauge } from "@fortawesome/free-solid-svg-icons/faGauge"; +export { definition as faGaugeHigh } from "@fortawesome/free-solid-svg-icons/faGaugeHigh"; +export { definition as faGaugeMed } from "@fortawesome/free-solid-svg-icons/faGaugeMed"; +export { definition as faGaugeSimple } from "@fortawesome/free-solid-svg-icons/faGaugeSimple"; +export { definition as faGaugeSimpleHigh } from "@fortawesome/free-solid-svg-icons/faGaugeSimpleHigh"; +export { definition as faGaugeSimpleMed } from "@fortawesome/free-solid-svg-icons/faGaugeSimpleMed"; +export { definition as faGavel } from "@fortawesome/free-solid-svg-icons/faGavel"; +export { definition as faGbp } from "@fortawesome/free-solid-svg-icons/faGbp"; +export { definition as faGear } from "@fortawesome/free-solid-svg-icons/faGear"; +export { definition as faGears } from "@fortawesome/free-solid-svg-icons/faGears"; +export { definition as faGem } from "@fortawesome/free-solid-svg-icons/faGem"; +export { definition as faGenderless } from "@fortawesome/free-solid-svg-icons/faGenderless"; +export { definition as faGhost } from "@fortawesome/free-solid-svg-icons/faGhost"; +export { definition as faGift } from "@fortawesome/free-solid-svg-icons/faGift"; +export { definition as faGifts } from "@fortawesome/free-solid-svg-icons/faGifts"; +export { definition as faGlassCheers } from "@fortawesome/free-solid-svg-icons/faGlassCheers"; +export { definition as faGlassMartini } from "@fortawesome/free-solid-svg-icons/faGlassMartini"; +export { definition as faGlassMartiniAlt } from "@fortawesome/free-solid-svg-icons/faGlassMartiniAlt"; +export { definition as faGlassWater } from "@fortawesome/free-solid-svg-icons/faGlassWater"; +export { definition as faGlassWaterDroplet } from "@fortawesome/free-solid-svg-icons/faGlassWaterDroplet"; +export { definition as faGlassWhiskey } from "@fortawesome/free-solid-svg-icons/faGlassWhiskey"; +export { definition as faGlasses } from "@fortawesome/free-solid-svg-icons/faGlasses"; +export { definition as faGlobe } from "@fortawesome/free-solid-svg-icons/faGlobe"; +export { definition as faGlobeAfrica } from "@fortawesome/free-solid-svg-icons/faGlobeAfrica"; +export { definition as faGlobeAmericas } from "@fortawesome/free-solid-svg-icons/faGlobeAmericas"; +export { definition as faGlobeAsia } from "@fortawesome/free-solid-svg-icons/faGlobeAsia"; +export { definition as faGlobeEurope } from "@fortawesome/free-solid-svg-icons/faGlobeEurope"; +export { definition as faGlobeOceania } from "@fortawesome/free-solid-svg-icons/faGlobeOceania"; +export { definition as faGolfBall } from "@fortawesome/free-solid-svg-icons/faGolfBall"; +export { definition as faGolfBallTee } from "@fortawesome/free-solid-svg-icons/faGolfBallTee"; +export { definition as faGopuram } from "@fortawesome/free-solid-svg-icons/faGopuram"; +export { definition as faGraduationCap } from "@fortawesome/free-solid-svg-icons/faGraduationCap"; +export { definition as faGreaterThan } from "@fortawesome/free-solid-svg-icons/faGreaterThan"; +export { definition as faGreaterThanEqual } from "@fortawesome/free-solid-svg-icons/faGreaterThanEqual"; +export { definition as faGrimace } from "@fortawesome/free-solid-svg-icons/faGrimace"; +export { definition as faGrin } from "@fortawesome/free-solid-svg-icons/faGrin"; +export { definition as faGrinAlt } from "@fortawesome/free-solid-svg-icons/faGrinAlt"; +export { definition as faGrinBeam } from "@fortawesome/free-solid-svg-icons/faGrinBeam"; +export { definition as faGrinBeamSweat } from "@fortawesome/free-solid-svg-icons/faGrinBeamSweat"; +export { definition as faGrinHearts } from "@fortawesome/free-solid-svg-icons/faGrinHearts"; +export { definition as faGrinSquint } from "@fortawesome/free-solid-svg-icons/faGrinSquint"; +export { definition as faGrinSquintTears } from "@fortawesome/free-solid-svg-icons/faGrinSquintTears"; +export { definition as faGrinStars } from "@fortawesome/free-solid-svg-icons/faGrinStars"; +export { definition as faGrinTears } from "@fortawesome/free-solid-svg-icons/faGrinTears"; +export { definition as faGrinTongue } from "@fortawesome/free-solid-svg-icons/faGrinTongue"; +export { definition as faGrinTongueSquint } from "@fortawesome/free-solid-svg-icons/faGrinTongueSquint"; +export { definition as faGrinTongueWink } from "@fortawesome/free-solid-svg-icons/faGrinTongueWink"; +export { definition as faGrinWink } from "@fortawesome/free-solid-svg-icons/faGrinWink"; +export { definition as faGrip } from "@fortawesome/free-solid-svg-icons/faGrip"; +export { definition as faGripHorizontal } from "@fortawesome/free-solid-svg-icons/faGripHorizontal"; +export { definition as faGripLines } from "@fortawesome/free-solid-svg-icons/faGripLines"; +export { definition as faGripLinesVertical } from "@fortawesome/free-solid-svg-icons/faGripLinesVertical"; +export { definition as faGripVertical } from "@fortawesome/free-solid-svg-icons/faGripVertical"; +export { definition as faGroupArrowsRotate } from "@fortawesome/free-solid-svg-icons/faGroupArrowsRotate"; +export { definition as faGuaraniSign } from "@fortawesome/free-solid-svg-icons/faGuaraniSign"; +export { definition as faGuitar } from "@fortawesome/free-solid-svg-icons/faGuitar"; +export { definition as faGun } from "@fortawesome/free-solid-svg-icons/faGun"; +export { definition as faH } from "@fortawesome/free-solid-svg-icons/faH"; +export { definition as faHSquare } from "@fortawesome/free-solid-svg-icons/faHSquare"; +export { definition as faHamburger } from "@fortawesome/free-solid-svg-icons/faHamburger"; +export { definition as faHammer } from "@fortawesome/free-solid-svg-icons/faHammer"; +export { definition as faHamsa } from "@fortawesome/free-solid-svg-icons/faHamsa"; +export { definition as faHand } from "@fortawesome/free-solid-svg-icons/faHand"; +export { definition as faHandBackFist } from "@fortawesome/free-solid-svg-icons/faHandBackFist"; +export { definition as faHandDots } from "@fortawesome/free-solid-svg-icons/faHandDots"; +export { definition as faHandFist } from "@fortawesome/free-solid-svg-icons/faHandFist"; +export { definition as faHandHolding } from "@fortawesome/free-solid-svg-icons/faHandHolding"; +export { definition as faHandHoldingDollar } from "@fortawesome/free-solid-svg-icons/faHandHoldingDollar"; +export { definition as faHandHoldingDroplet } from "@fortawesome/free-solid-svg-icons/faHandHoldingDroplet"; +export { definition as faHandHoldingHand } from "@fortawesome/free-solid-svg-icons/faHandHoldingHand"; +export { definition as faHandHoldingHeart } from "@fortawesome/free-solid-svg-icons/faHandHoldingHeart"; +export { definition as faHandHoldingMedical } from "@fortawesome/free-solid-svg-icons/faHandHoldingMedical"; +export { definition as faHandHoldingUsd } from "@fortawesome/free-solid-svg-icons/faHandHoldingUsd"; +export { definition as faHandHoldingWater } from "@fortawesome/free-solid-svg-icons/faHandHoldingWater"; +export { definition as faHandLizard } from "@fortawesome/free-solid-svg-icons/faHandLizard"; +export { definition as faHandMiddleFinger } from "@fortawesome/free-solid-svg-icons/faHandMiddleFinger"; +export { definition as faHandPaper } from "@fortawesome/free-solid-svg-icons/faHandPaper"; +export { definition as faHandPeace } from "@fortawesome/free-solid-svg-icons/faHandPeace"; +export { definition as faHandPointDown } from "@fortawesome/free-solid-svg-icons/faHandPointDown"; +export { definition as faHandPointLeft } from "@fortawesome/free-solid-svg-icons/faHandPointLeft"; +export { definition as faHandPointRight } from "@fortawesome/free-solid-svg-icons/faHandPointRight"; +export { definition as faHandPointUp } from "@fortawesome/free-solid-svg-icons/faHandPointUp"; +export { definition as faHandPointer } from "@fortawesome/free-solid-svg-icons/faHandPointer"; +export { definition as faHandRock } from "@fortawesome/free-solid-svg-icons/faHandRock"; +export { definition as faHandScissors } from "@fortawesome/free-solid-svg-icons/faHandScissors"; +export { definition as faHandSparkles } from "@fortawesome/free-solid-svg-icons/faHandSparkles"; +export { definition as faHandSpock } from "@fortawesome/free-solid-svg-icons/faHandSpock"; +export { definition as faHandcuffs } from "@fortawesome/free-solid-svg-icons/faHandcuffs"; +export { definition as faHands } from "@fortawesome/free-solid-svg-icons/faHands"; +export { definition as faHandsAmericanSignLanguageInterpreting } from "@fortawesome/free-solid-svg-icons/faHandsAmericanSignLanguageInterpreting"; +export { definition as faHandsAslInterpreting } from "@fortawesome/free-solid-svg-icons/faHandsAslInterpreting"; +export { definition as faHandsBound } from "@fortawesome/free-solid-svg-icons/faHandsBound"; +export { definition as faHandsBubbles } from "@fortawesome/free-solid-svg-icons/faHandsBubbles"; +export { definition as faHandsClapping } from "@fortawesome/free-solid-svg-icons/faHandsClapping"; +export { definition as faHandsHelping } from "@fortawesome/free-solid-svg-icons/faHandsHelping"; +export { definition as faHandsHolding } from "@fortawesome/free-solid-svg-icons/faHandsHolding"; +export { definition as faHandsHoldingChild } from "@fortawesome/free-solid-svg-icons/faHandsHoldingChild"; +export { definition as faHandsHoldingCircle } from "@fortawesome/free-solid-svg-icons/faHandsHoldingCircle"; +export { definition as faHandsPraying } from "@fortawesome/free-solid-svg-icons/faHandsPraying"; +export { definition as faHandsWash } from "@fortawesome/free-solid-svg-icons/faHandsWash"; +export { definition as faHandshake } from "@fortawesome/free-solid-svg-icons/faHandshake"; +export { definition as faHandshakeAlt } from "@fortawesome/free-solid-svg-icons/faHandshakeAlt"; +export { definition as faHandshakeAltSlash } from "@fortawesome/free-solid-svg-icons/faHandshakeAltSlash"; +export { definition as faHandshakeAngle } from "@fortawesome/free-solid-svg-icons/faHandshakeAngle"; +export { definition as faHandshakeSimple } from "@fortawesome/free-solid-svg-icons/faHandshakeSimple"; +export { definition as faHandshakeSimpleSlash } from "@fortawesome/free-solid-svg-icons/faHandshakeSimpleSlash"; +export { definition as faHandshakeSlash } from "@fortawesome/free-solid-svg-icons/faHandshakeSlash"; +export { definition as faHanukiah } from "@fortawesome/free-solid-svg-icons/faHanukiah"; +export { definition as faHardDrive } from "@fortawesome/free-solid-svg-icons/faHardDrive"; +export { definition as faHardHat } from "@fortawesome/free-solid-svg-icons/faHardHat"; +export { definition as faHardOfHearing } from "@fortawesome/free-solid-svg-icons/faHardOfHearing"; +export { definition as faHashtag } from "@fortawesome/free-solid-svg-icons/faHashtag"; +export { definition as faHatCowboy } from "@fortawesome/free-solid-svg-icons/faHatCowboy"; +export { definition as faHatCowboySide } from "@fortawesome/free-solid-svg-icons/faHatCowboySide"; +export { definition as faHatHard } from "@fortawesome/free-solid-svg-icons/faHatHard"; +export { definition as faHatWizard } from "@fortawesome/free-solid-svg-icons/faHatWizard"; +export { definition as faHaykal } from "@fortawesome/free-solid-svg-icons/faHaykal"; +export { definition as faHdd } from "@fortawesome/free-solid-svg-icons/faHdd"; +export { definition as faHeadSideCough } from "@fortawesome/free-solid-svg-icons/faHeadSideCough"; +export { definition as faHeadSideCoughSlash } from "@fortawesome/free-solid-svg-icons/faHeadSideCoughSlash"; +export { definition as faHeadSideMask } from "@fortawesome/free-solid-svg-icons/faHeadSideMask"; +export { definition as faHeadSideVirus } from "@fortawesome/free-solid-svg-icons/faHeadSideVirus"; +export { definition as faHeader } from "@fortawesome/free-solid-svg-icons/faHeader"; +export { definition as faHeading } from "@fortawesome/free-solid-svg-icons/faHeading"; +export { definition as faHeadphones } from "@fortawesome/free-solid-svg-icons/faHeadphones"; +export { definition as faHeadphonesAlt } from "@fortawesome/free-solid-svg-icons/faHeadphonesAlt"; +export { definition as faHeadphonesSimple } from "@fortawesome/free-solid-svg-icons/faHeadphonesSimple"; +export { definition as faHeadset } from "@fortawesome/free-solid-svg-icons/faHeadset"; +export { definition as faHeart } from "@fortawesome/free-solid-svg-icons/faHeart"; +export { definition as faHeartBroken } from "@fortawesome/free-solid-svg-icons/faHeartBroken"; +export { definition as faHeartCircleBolt } from "@fortawesome/free-solid-svg-icons/faHeartCircleBolt"; +export { definition as faHeartCircleCheck } from "@fortawesome/free-solid-svg-icons/faHeartCircleCheck"; +export { definition as faHeartCircleExclamation } from "@fortawesome/free-solid-svg-icons/faHeartCircleExclamation"; +export { definition as faHeartCircleMinus } from "@fortawesome/free-solid-svg-icons/faHeartCircleMinus"; +export { definition as faHeartCirclePlus } from "@fortawesome/free-solid-svg-icons/faHeartCirclePlus"; +export { definition as faHeartCircleXmark } from "@fortawesome/free-solid-svg-icons/faHeartCircleXmark"; +export { definition as faHeartCrack } from "@fortawesome/free-solid-svg-icons/faHeartCrack"; +export { definition as faHeartMusicCameraBolt } from "@fortawesome/free-solid-svg-icons/faHeartMusicCameraBolt"; +export { definition as faHeartPulse } from "@fortawesome/free-solid-svg-icons/faHeartPulse"; +export { definition as faHeartbeat } from "@fortawesome/free-solid-svg-icons/faHeartbeat"; +export { definition as faHelicopter } from "@fortawesome/free-solid-svg-icons/faHelicopter"; +export { definition as faHelicopterSymbol } from "@fortawesome/free-solid-svg-icons/faHelicopterSymbol"; +export { definition as faHelmetSafety } from "@fortawesome/free-solid-svg-icons/faHelmetSafety"; +export { definition as faHelmetUn } from "@fortawesome/free-solid-svg-icons/faHelmetUn"; +export { definition as faHexagonNodes } from "@fortawesome/free-solid-svg-icons/faHexagonNodes"; +export { definition as faHexagonNodesBolt } from "@fortawesome/free-solid-svg-icons/faHexagonNodesBolt"; +export { definition as faHighlighter } from "@fortawesome/free-solid-svg-icons/faHighlighter"; +export { definition as faHiking } from "@fortawesome/free-solid-svg-icons/faHiking"; +export { definition as faHillAvalanche } from "@fortawesome/free-solid-svg-icons/faHillAvalanche"; +export { definition as faHillRockslide } from "@fortawesome/free-solid-svg-icons/faHillRockslide"; +export { definition as faHippo } from "@fortawesome/free-solid-svg-icons/faHippo"; +export { definition as faHistory } from "@fortawesome/free-solid-svg-icons/faHistory"; +export { definition as faHockeyPuck } from "@fortawesome/free-solid-svg-icons/faHockeyPuck"; +export { definition as faHollyBerry } from "@fortawesome/free-solid-svg-icons/faHollyBerry"; +export { definition as faHome } from "@fortawesome/free-solid-svg-icons/faHome"; +export { definition as faHomeAlt } from "@fortawesome/free-solid-svg-icons/faHomeAlt"; +export { definition as faHomeLg } from "@fortawesome/free-solid-svg-icons/faHomeLg"; +export { definition as faHomeLgAlt } from "@fortawesome/free-solid-svg-icons/faHomeLgAlt"; +export { definition as faHomeUser } from "@fortawesome/free-solid-svg-icons/faHomeUser"; +export { definition as faHorse } from "@fortawesome/free-solid-svg-icons/faHorse"; +export { definition as faHorseHead } from "@fortawesome/free-solid-svg-icons/faHorseHead"; +export { definition as faHospital } from "@fortawesome/free-solid-svg-icons/faHospital"; +export { definition as faHospitalAlt } from "@fortawesome/free-solid-svg-icons/faHospitalAlt"; +export { definition as faHospitalSymbol } from "@fortawesome/free-solid-svg-icons/faHospitalSymbol"; +export { definition as faHospitalUser } from "@fortawesome/free-solid-svg-icons/faHospitalUser"; +export { definition as faHospitalWide } from "@fortawesome/free-solid-svg-icons/faHospitalWide"; +export { definition as faHotTub } from "@fortawesome/free-solid-svg-icons/faHotTub"; +export { definition as faHotTubPerson } from "@fortawesome/free-solid-svg-icons/faHotTubPerson"; +export { definition as faHotdog } from "@fortawesome/free-solid-svg-icons/faHotdog"; +export { definition as faHotel } from "@fortawesome/free-solid-svg-icons/faHotel"; +export { definition as faHourglass } from "@fortawesome/free-solid-svg-icons/faHourglass"; +export { definition as faHourglass1 } from "@fortawesome/free-solid-svg-icons/faHourglass1"; +export { definition as faHourglass2 } from "@fortawesome/free-solid-svg-icons/faHourglass2"; +export { definition as faHourglass3 } from "@fortawesome/free-solid-svg-icons/faHourglass3"; +export { definition as faHourglassEmpty } from "@fortawesome/free-solid-svg-icons/faHourglassEmpty"; +export { definition as faHourglassEnd } from "@fortawesome/free-solid-svg-icons/faHourglassEnd"; +export { definition as faHourglassHalf } from "@fortawesome/free-solid-svg-icons/faHourglassHalf"; +export { definition as faHourglassStart } from "@fortawesome/free-solid-svg-icons/faHourglassStart"; +export { definition as faHouse } from "@fortawesome/free-solid-svg-icons/faHouse"; +export { definition as faHouseChimney } from "@fortawesome/free-solid-svg-icons/faHouseChimney"; +export { definition as faHouseChimneyCrack } from "@fortawesome/free-solid-svg-icons/faHouseChimneyCrack"; +export { definition as faHouseChimneyMedical } from "@fortawesome/free-solid-svg-icons/faHouseChimneyMedical"; +export { definition as faHouseChimneyUser } from "@fortawesome/free-solid-svg-icons/faHouseChimneyUser"; +export { definition as faHouseChimneyWindow } from "@fortawesome/free-solid-svg-icons/faHouseChimneyWindow"; +export { definition as faHouseCircleCheck } from "@fortawesome/free-solid-svg-icons/faHouseCircleCheck"; +export { definition as faHouseCircleExclamation } from "@fortawesome/free-solid-svg-icons/faHouseCircleExclamation"; +export { definition as faHouseCircleXmark } from "@fortawesome/free-solid-svg-icons/faHouseCircleXmark"; +export { definition as faHouseCrack } from "@fortawesome/free-solid-svg-icons/faHouseCrack"; +export { definition as faHouseDamage } from "@fortawesome/free-solid-svg-icons/faHouseDamage"; +export { definition as faHouseFire } from "@fortawesome/free-solid-svg-icons/faHouseFire"; +export { definition as faHouseFlag } from "@fortawesome/free-solid-svg-icons/faHouseFlag"; +export { definition as faHouseFloodWater } from "@fortawesome/free-solid-svg-icons/faHouseFloodWater"; +export { definition as faHouseFloodWaterCircleArrowRight } from "@fortawesome/free-solid-svg-icons/faHouseFloodWaterCircleArrowRight"; +export { definition as faHouseLaptop } from "@fortawesome/free-solid-svg-icons/faHouseLaptop"; +export { definition as faHouseLock } from "@fortawesome/free-solid-svg-icons/faHouseLock"; +export { definition as faHouseMedical } from "@fortawesome/free-solid-svg-icons/faHouseMedical"; +export { definition as faHouseMedicalCircleCheck } from "@fortawesome/free-solid-svg-icons/faHouseMedicalCircleCheck"; +export { definition as faHouseMedicalCircleExclamation } from "@fortawesome/free-solid-svg-icons/faHouseMedicalCircleExclamation"; +export { definition as faHouseMedicalCircleXmark } from "@fortawesome/free-solid-svg-icons/faHouseMedicalCircleXmark"; +export { definition as faHouseMedicalFlag } from "@fortawesome/free-solid-svg-icons/faHouseMedicalFlag"; +export { definition as faHouseSignal } from "@fortawesome/free-solid-svg-icons/faHouseSignal"; +export { definition as faHouseTsunami } from "@fortawesome/free-solid-svg-icons/faHouseTsunami"; +export { definition as faHouseUser } from "@fortawesome/free-solid-svg-icons/faHouseUser"; +export { definition as faHryvnia } from "@fortawesome/free-solid-svg-icons/faHryvnia"; +export { definition as faHryvniaSign } from "@fortawesome/free-solid-svg-icons/faHryvniaSign"; +export { definition as faHurricane } from "@fortawesome/free-solid-svg-icons/faHurricane"; +export { definition as faI } from "@fortawesome/free-solid-svg-icons/faI"; +export { definition as faICursor } from "@fortawesome/free-solid-svg-icons/faICursor"; +export { definition as faIceCream } from "@fortawesome/free-solid-svg-icons/faIceCream"; +export { definition as faIcicles } from "@fortawesome/free-solid-svg-icons/faIcicles"; +export { definition as faIcons } from "@fortawesome/free-solid-svg-icons/faIcons"; +export { definition as faIdBadge } from "@fortawesome/free-solid-svg-icons/faIdBadge"; +export { definition as faIdCard } from "@fortawesome/free-solid-svg-icons/faIdCard"; +export { definition as faIdCardAlt } from "@fortawesome/free-solid-svg-icons/faIdCardAlt"; +export { definition as faIdCardClip } from "@fortawesome/free-solid-svg-icons/faIdCardClip"; +export { definition as faIgloo } from "@fortawesome/free-solid-svg-icons/faIgloo"; +export { definition as faIls } from "@fortawesome/free-solid-svg-icons/faIls"; +export { definition as faImage } from "@fortawesome/free-solid-svg-icons/faImage"; +export { definition as faImagePortrait } from "@fortawesome/free-solid-svg-icons/faImagePortrait"; +export { definition as faImages } from "@fortawesome/free-solid-svg-icons/faImages"; +export { definition as faInbox } from "@fortawesome/free-solid-svg-icons/faInbox"; +export { definition as faIndent } from "@fortawesome/free-solid-svg-icons/faIndent"; +export { definition as faIndianRupee } from "@fortawesome/free-solid-svg-icons/faIndianRupee"; +export { definition as faIndianRupeeSign } from "@fortawesome/free-solid-svg-icons/faIndianRupeeSign"; +export { definition as faIndustry } from "@fortawesome/free-solid-svg-icons/faIndustry"; +export { definition as faInfinity } from "@fortawesome/free-solid-svg-icons/faInfinity"; +export { definition as faInfo } from "@fortawesome/free-solid-svg-icons/faInfo"; +export { definition as faInfoCircle } from "@fortawesome/free-solid-svg-icons/faInfoCircle"; +export { definition as faInr } from "@fortawesome/free-solid-svg-icons/faInr"; +export { definition as faInstitution } from "@fortawesome/free-solid-svg-icons/faInstitution"; +export { definition as faItalic } from "@fortawesome/free-solid-svg-icons/faItalic"; +export { definition as faJ } from "@fortawesome/free-solid-svg-icons/faJ"; +export { definition as faJar } from "@fortawesome/free-solid-svg-icons/faJar"; +export { definition as faJarWheat } from "@fortawesome/free-solid-svg-icons/faJarWheat"; +export { definition as faJedi } from "@fortawesome/free-solid-svg-icons/faJedi"; +export { definition as faJetFighter } from "@fortawesome/free-solid-svg-icons/faJetFighter"; +export { definition as faJetFighterUp } from "@fortawesome/free-solid-svg-icons/faJetFighterUp"; +export { definition as faJoint } from "@fortawesome/free-solid-svg-icons/faJoint"; +export { definition as faJournalWhills } from "@fortawesome/free-solid-svg-icons/faJournalWhills"; +export { definition as faJpy } from "@fortawesome/free-solid-svg-icons/faJpy"; +export { definition as faJugDetergent } from "@fortawesome/free-solid-svg-icons/faJugDetergent"; +export { definition as faK } from "@fortawesome/free-solid-svg-icons/faK"; +export { definition as faKaaba } from "@fortawesome/free-solid-svg-icons/faKaaba"; +export { definition as faKey } from "@fortawesome/free-solid-svg-icons/faKey"; +export { definition as faKeyboard } from "@fortawesome/free-solid-svg-icons/faKeyboard"; +export { definition as faKhanda } from "@fortawesome/free-solid-svg-icons/faKhanda"; +export { definition as faKipSign } from "@fortawesome/free-solid-svg-icons/faKipSign"; +export { definition as faKiss } from "@fortawesome/free-solid-svg-icons/faKiss"; +export { definition as faKissBeam } from "@fortawesome/free-solid-svg-icons/faKissBeam"; +export { definition as faKissWinkHeart } from "@fortawesome/free-solid-svg-icons/faKissWinkHeart"; +export { definition as faKitMedical } from "@fortawesome/free-solid-svg-icons/faKitMedical"; +export { definition as faKitchenSet } from "@fortawesome/free-solid-svg-icons/faKitchenSet"; +export { definition as faKiwiBird } from "@fortawesome/free-solid-svg-icons/faKiwiBird"; +export { definition as faKrw } from "@fortawesome/free-solid-svg-icons/faKrw"; +export { definition as faL } from "@fortawesome/free-solid-svg-icons/faL"; +export { definition as faLadderWater } from "@fortawesome/free-solid-svg-icons/faLadderWater"; +export { definition as faLandMineOn } from "@fortawesome/free-solid-svg-icons/faLandMineOn"; +export { definition as faLandmark } from "@fortawesome/free-solid-svg-icons/faLandmark"; +export { definition as faLandmarkAlt } from "@fortawesome/free-solid-svg-icons/faLandmarkAlt"; +export { definition as faLandmarkDome } from "@fortawesome/free-solid-svg-icons/faLandmarkDome"; +export { definition as faLandmarkFlag } from "@fortawesome/free-solid-svg-icons/faLandmarkFlag"; +export { definition as faLanguage } from "@fortawesome/free-solid-svg-icons/faLanguage"; +export { definition as faLaptop } from "@fortawesome/free-solid-svg-icons/faLaptop"; +export { definition as faLaptopCode } from "@fortawesome/free-solid-svg-icons/faLaptopCode"; +export { definition as faLaptopFile } from "@fortawesome/free-solid-svg-icons/faLaptopFile"; +export { definition as faLaptopHouse } from "@fortawesome/free-solid-svg-icons/faLaptopHouse"; +export { definition as faLaptopMedical } from "@fortawesome/free-solid-svg-icons/faLaptopMedical"; +export { definition as faLariSign } from "@fortawesome/free-solid-svg-icons/faLariSign"; +export { definition as faLaugh } from "@fortawesome/free-solid-svg-icons/faLaugh"; +export { definition as faLaughBeam } from "@fortawesome/free-solid-svg-icons/faLaughBeam"; +export { definition as faLaughSquint } from "@fortawesome/free-solid-svg-icons/faLaughSquint"; +export { definition as faLaughWink } from "@fortawesome/free-solid-svg-icons/faLaughWink"; +export { definition as faLayerGroup } from "@fortawesome/free-solid-svg-icons/faLayerGroup"; +export { definition as faLeaf } from "@fortawesome/free-solid-svg-icons/faLeaf"; +export { definition as faLeftLong } from "@fortawesome/free-solid-svg-icons/faLeftLong"; +export { definition as faLeftRight } from "@fortawesome/free-solid-svg-icons/faLeftRight"; +export { definition as faLegal } from "@fortawesome/free-solid-svg-icons/faLegal"; +export { definition as faLemon } from "@fortawesome/free-solid-svg-icons/faLemon"; +export { definition as faLessThan } from "@fortawesome/free-solid-svg-icons/faLessThan"; +export { definition as faLessThanEqual } from "@fortawesome/free-solid-svg-icons/faLessThanEqual"; +export { definition as faLevelDown } from "@fortawesome/free-solid-svg-icons/faLevelDown"; +export { definition as faLevelDownAlt } from "@fortawesome/free-solid-svg-icons/faLevelDownAlt"; +export { definition as faLevelUp } from "@fortawesome/free-solid-svg-icons/faLevelUp"; +export { definition as faLevelUpAlt } from "@fortawesome/free-solid-svg-icons/faLevelUpAlt"; +export { definition as faLifeRing } from "@fortawesome/free-solid-svg-icons/faLifeRing"; +export { definition as faLightbulb } from "@fortawesome/free-solid-svg-icons/faLightbulb"; +export { definition as faLineChart } from "@fortawesome/free-solid-svg-icons/faLineChart"; +export { definition as faLinesLeaning } from "@fortawesome/free-solid-svg-icons/faLinesLeaning"; +export { definition as faLink } from "@fortawesome/free-solid-svg-icons/faLink"; +export { definition as faLinkSlash } from "@fortawesome/free-solid-svg-icons/faLinkSlash"; +export { definition as faLiraSign } from "@fortawesome/free-solid-svg-icons/faLiraSign"; +export { definition as faList } from "@fortawesome/free-solid-svg-icons/faList"; +export { definition as faList12 } from "@fortawesome/free-solid-svg-icons/faList12"; +export { definition as faListAlt } from "@fortawesome/free-solid-svg-icons/faListAlt"; +export { definition as faListCheck } from "@fortawesome/free-solid-svg-icons/faListCheck"; +export { definition as faListDots } from "@fortawesome/free-solid-svg-icons/faListDots"; +export { definition as faListNumeric } from "@fortawesome/free-solid-svg-icons/faListNumeric"; +export { definition as faListOl } from "@fortawesome/free-solid-svg-icons/faListOl"; +export { definition as faListSquares } from "@fortawesome/free-solid-svg-icons/faListSquares"; +export { definition as faListUl } from "@fortawesome/free-solid-svg-icons/faListUl"; +export { definition as faLitecoinSign } from "@fortawesome/free-solid-svg-icons/faLitecoinSign"; +export { definition as faLocation } from "@fortawesome/free-solid-svg-icons/faLocation"; +export { definition as faLocationArrow } from "@fortawesome/free-solid-svg-icons/faLocationArrow"; +export { definition as faLocationCrosshairs } from "@fortawesome/free-solid-svg-icons/faLocationCrosshairs"; +export { definition as faLocationDot } from "@fortawesome/free-solid-svg-icons/faLocationDot"; +export { definition as faLocationPin } from "@fortawesome/free-solid-svg-icons/faLocationPin"; +export { definition as faLocationPinLock } from "@fortawesome/free-solid-svg-icons/faLocationPinLock"; +export { definition as faLock } from "@fortawesome/free-solid-svg-icons/faLock"; +export { definition as faLockOpen } from "@fortawesome/free-solid-svg-icons/faLockOpen"; +export { definition as faLocust } from "@fortawesome/free-solid-svg-icons/faLocust"; +export { definition as faLongArrowAltDown } from "@fortawesome/free-solid-svg-icons/faLongArrowAltDown"; +export { definition as faLongArrowAltLeft } from "@fortawesome/free-solid-svg-icons/faLongArrowAltLeft"; +export { definition as faLongArrowAltRight } from "@fortawesome/free-solid-svg-icons/faLongArrowAltRight"; +export { definition as faLongArrowAltUp } from "@fortawesome/free-solid-svg-icons/faLongArrowAltUp"; +export { definition as faLongArrowDown } from "@fortawesome/free-solid-svg-icons/faLongArrowDown"; +export { definition as faLongArrowLeft } from "@fortawesome/free-solid-svg-icons/faLongArrowLeft"; +export { definition as faLongArrowRight } from "@fortawesome/free-solid-svg-icons/faLongArrowRight"; +export { definition as faLongArrowUp } from "@fortawesome/free-solid-svg-icons/faLongArrowUp"; +export { definition as faLowVision } from "@fortawesome/free-solid-svg-icons/faLowVision"; +export { definition as faLuggageCart } from "@fortawesome/free-solid-svg-icons/faLuggageCart"; +export { definition as faLungs } from "@fortawesome/free-solid-svg-icons/faLungs"; +export { definition as faLungsVirus } from "@fortawesome/free-solid-svg-icons/faLungsVirus"; +export { definition as faM } from "@fortawesome/free-solid-svg-icons/faM"; +export { definition as faMagic } from "@fortawesome/free-solid-svg-icons/faMagic"; +export { definition as faMagicWandSparkles } from "@fortawesome/free-solid-svg-icons/faMagicWandSparkles"; +export { definition as faMagnet } from "@fortawesome/free-solid-svg-icons/faMagnet"; +export { definition as faMagnifyingGlass } from "@fortawesome/free-solid-svg-icons/faMagnifyingGlass"; +export { definition as faMagnifyingGlassArrowRight } from "@fortawesome/free-solid-svg-icons/faMagnifyingGlassArrowRight"; +export { definition as faMagnifyingGlassChart } from "@fortawesome/free-solid-svg-icons/faMagnifyingGlassChart"; +export { definition as faMagnifyingGlassDollar } from "@fortawesome/free-solid-svg-icons/faMagnifyingGlassDollar"; +export { definition as faMagnifyingGlassLocation } from "@fortawesome/free-solid-svg-icons/faMagnifyingGlassLocation"; +export { definition as faMagnifyingGlassMinus } from "@fortawesome/free-solid-svg-icons/faMagnifyingGlassMinus"; +export { definition as faMagnifyingGlassPlus } from "@fortawesome/free-solid-svg-icons/faMagnifyingGlassPlus"; +export { definition as faMailBulk } from "@fortawesome/free-solid-svg-icons/faMailBulk"; +export { definition as faMailForward } from "@fortawesome/free-solid-svg-icons/faMailForward"; +export { definition as faMailReply } from "@fortawesome/free-solid-svg-icons/faMailReply"; +export { definition as faMailReplyAll } from "@fortawesome/free-solid-svg-icons/faMailReplyAll"; +export { definition as faMale } from "@fortawesome/free-solid-svg-icons/faMale"; +export { definition as faManatSign } from "@fortawesome/free-solid-svg-icons/faManatSign"; +export { definition as faMap } from "@fortawesome/free-solid-svg-icons/faMap"; +export { definition as faMapLocation } from "@fortawesome/free-solid-svg-icons/faMapLocation"; +export { definition as faMapLocationDot } from "@fortawesome/free-solid-svg-icons/faMapLocationDot"; +export { definition as faMapMarked } from "@fortawesome/free-solid-svg-icons/faMapMarked"; +export { definition as faMapMarkedAlt } from "@fortawesome/free-solid-svg-icons/faMapMarkedAlt"; +export { definition as faMapMarker } from "@fortawesome/free-solid-svg-icons/faMapMarker"; +export { definition as faMapMarkerAlt } from "@fortawesome/free-solid-svg-icons/faMapMarkerAlt"; +export { definition as faMapPin } from "@fortawesome/free-solid-svg-icons/faMapPin"; +export { definition as faMapSigns } from "@fortawesome/free-solid-svg-icons/faMapSigns"; +export { definition as faMarker } from "@fortawesome/free-solid-svg-icons/faMarker"; +export { definition as faMars } from "@fortawesome/free-solid-svg-icons/faMars"; +export { definition as faMarsAndVenus } from "@fortawesome/free-solid-svg-icons/faMarsAndVenus"; +export { definition as faMarsAndVenusBurst } from "@fortawesome/free-solid-svg-icons/faMarsAndVenusBurst"; +export { definition as faMarsDouble } from "@fortawesome/free-solid-svg-icons/faMarsDouble"; +export { definition as faMarsStroke } from "@fortawesome/free-solid-svg-icons/faMarsStroke"; +export { definition as faMarsStrokeH } from "@fortawesome/free-solid-svg-icons/faMarsStrokeH"; +export { definition as faMarsStrokeRight } from "@fortawesome/free-solid-svg-icons/faMarsStrokeRight"; +export { definition as faMarsStrokeUp } from "@fortawesome/free-solid-svg-icons/faMarsStrokeUp"; +export { definition as faMarsStrokeV } from "@fortawesome/free-solid-svg-icons/faMarsStrokeV"; +export { definition as faMartiniGlass } from "@fortawesome/free-solid-svg-icons/faMartiniGlass"; +export { definition as faMartiniGlassCitrus } from "@fortawesome/free-solid-svg-icons/faMartiniGlassCitrus"; +export { definition as faMartiniGlassEmpty } from "@fortawesome/free-solid-svg-icons/faMartiniGlassEmpty"; +export { definition as faMask } from "@fortawesome/free-solid-svg-icons/faMask"; +export { definition as faMaskFace } from "@fortawesome/free-solid-svg-icons/faMaskFace"; +export { definition as faMaskVentilator } from "@fortawesome/free-solid-svg-icons/faMaskVentilator"; +export { definition as faMasksTheater } from "@fortawesome/free-solid-svg-icons/faMasksTheater"; +export { definition as faMattressPillow } from "@fortawesome/free-solid-svg-icons/faMattressPillow"; +export { definition as faMaximize } from "@fortawesome/free-solid-svg-icons/faMaximize"; +export { definition as faMedal } from "@fortawesome/free-solid-svg-icons/faMedal"; +export { definition as faMedkit } from "@fortawesome/free-solid-svg-icons/faMedkit"; +export { definition as faMeh } from "@fortawesome/free-solid-svg-icons/faMeh"; +export { definition as faMehBlank } from "@fortawesome/free-solid-svg-icons/faMehBlank"; +export { definition as faMehRollingEyes } from "@fortawesome/free-solid-svg-icons/faMehRollingEyes"; +export { definition as faMemory } from "@fortawesome/free-solid-svg-icons/faMemory"; +export { definition as faMenorah } from "@fortawesome/free-solid-svg-icons/faMenorah"; +export { definition as faMercury } from "@fortawesome/free-solid-svg-icons/faMercury"; +export { definition as faMessage } from "@fortawesome/free-solid-svg-icons/faMessage"; +export { definition as faMeteor } from "@fortawesome/free-solid-svg-icons/faMeteor"; +export { definition as faMicrochip } from "@fortawesome/free-solid-svg-icons/faMicrochip"; +export { definition as faMicrophone } from "@fortawesome/free-solid-svg-icons/faMicrophone"; +export { definition as faMicrophoneAlt } from "@fortawesome/free-solid-svg-icons/faMicrophoneAlt"; +export { definition as faMicrophoneAltSlash } from "@fortawesome/free-solid-svg-icons/faMicrophoneAltSlash"; +export { definition as faMicrophoneLines } from "@fortawesome/free-solid-svg-icons/faMicrophoneLines"; +export { definition as faMicrophoneLinesSlash } from "@fortawesome/free-solid-svg-icons/faMicrophoneLinesSlash"; +export { definition as faMicrophoneSlash } from "@fortawesome/free-solid-svg-icons/faMicrophoneSlash"; +export { definition as faMicroscope } from "@fortawesome/free-solid-svg-icons/faMicroscope"; +export { definition as faMillSign } from "@fortawesome/free-solid-svg-icons/faMillSign"; +export { definition as faMinimize } from "@fortawesome/free-solid-svg-icons/faMinimize"; +export { definition as faMinus } from "@fortawesome/free-solid-svg-icons/faMinus"; +export { definition as faMinusCircle } from "@fortawesome/free-solid-svg-icons/faMinusCircle"; +export { definition as faMinusSquare } from "@fortawesome/free-solid-svg-icons/faMinusSquare"; +export { definition as faMitten } from "@fortawesome/free-solid-svg-icons/faMitten"; +export { definition as faMobile } from "@fortawesome/free-solid-svg-icons/faMobile"; +export { definition as faMobileAlt } from "@fortawesome/free-solid-svg-icons/faMobileAlt"; +export { definition as faMobileAndroid } from "@fortawesome/free-solid-svg-icons/faMobileAndroid"; +export { definition as faMobileAndroidAlt } from "@fortawesome/free-solid-svg-icons/faMobileAndroidAlt"; +export { definition as faMobileButton } from "@fortawesome/free-solid-svg-icons/faMobileButton"; +export { definition as faMobilePhone } from "@fortawesome/free-solid-svg-icons/faMobilePhone"; +export { definition as faMobileRetro } from "@fortawesome/free-solid-svg-icons/faMobileRetro"; +export { definition as faMobileScreen } from "@fortawesome/free-solid-svg-icons/faMobileScreen"; +export { definition as faMobileScreenButton } from "@fortawesome/free-solid-svg-icons/faMobileScreenButton"; +export { definition as faMoneyBill } from "@fortawesome/free-solid-svg-icons/faMoneyBill"; +export { definition as faMoneyBill1 } from "@fortawesome/free-solid-svg-icons/faMoneyBill1"; +export { definition as faMoneyBill1Wave } from "@fortawesome/free-solid-svg-icons/faMoneyBill1Wave"; +export { definition as faMoneyBillAlt } from "@fortawesome/free-solid-svg-icons/faMoneyBillAlt"; +export { definition as faMoneyBillTransfer } from "@fortawesome/free-solid-svg-icons/faMoneyBillTransfer"; +export { definition as faMoneyBillTrendUp } from "@fortawesome/free-solid-svg-icons/faMoneyBillTrendUp"; +export { definition as faMoneyBillWave } from "@fortawesome/free-solid-svg-icons/faMoneyBillWave"; +export { definition as faMoneyBillWaveAlt } from "@fortawesome/free-solid-svg-icons/faMoneyBillWaveAlt"; +export { definition as faMoneyBillWheat } from "@fortawesome/free-solid-svg-icons/faMoneyBillWheat"; +export { definition as faMoneyBills } from "@fortawesome/free-solid-svg-icons/faMoneyBills"; +export { definition as faMoneyCheck } from "@fortawesome/free-solid-svg-icons/faMoneyCheck"; +export { definition as faMoneyCheckAlt } from "@fortawesome/free-solid-svg-icons/faMoneyCheckAlt"; +export { definition as faMoneyCheckDollar } from "@fortawesome/free-solid-svg-icons/faMoneyCheckDollar"; +export { definition as faMonument } from "@fortawesome/free-solid-svg-icons/faMonument"; +export { definition as faMoon } from "@fortawesome/free-solid-svg-icons/faMoon"; +export { definition as faMortarBoard } from "@fortawesome/free-solid-svg-icons/faMortarBoard"; +export { definition as faMortarPestle } from "@fortawesome/free-solid-svg-icons/faMortarPestle"; +export { definition as faMosque } from "@fortawesome/free-solid-svg-icons/faMosque"; +export { definition as faMosquito } from "@fortawesome/free-solid-svg-icons/faMosquito"; +export { definition as faMosquitoNet } from "@fortawesome/free-solid-svg-icons/faMosquitoNet"; +export { definition as faMotorcycle } from "@fortawesome/free-solid-svg-icons/faMotorcycle"; +export { definition as faMound } from "@fortawesome/free-solid-svg-icons/faMound"; +export { definition as faMountain } from "@fortawesome/free-solid-svg-icons/faMountain"; +export { definition as faMountainCity } from "@fortawesome/free-solid-svg-icons/faMountainCity"; +export { definition as faMountainSun } from "@fortawesome/free-solid-svg-icons/faMountainSun"; +export { definition as faMouse } from "@fortawesome/free-solid-svg-icons/faMouse"; +export { definition as faMousePointer } from "@fortawesome/free-solid-svg-icons/faMousePointer"; +export { definition as faMugHot } from "@fortawesome/free-solid-svg-icons/faMugHot"; +export { definition as faMugSaucer } from "@fortawesome/free-solid-svg-icons/faMugSaucer"; +export { definition as faMultiply } from "@fortawesome/free-solid-svg-icons/faMultiply"; +export { definition as faMuseum } from "@fortawesome/free-solid-svg-icons/faMuseum"; +export { definition as faMusic } from "@fortawesome/free-solid-svg-icons/faMusic"; +export { definition as faN } from "@fortawesome/free-solid-svg-icons/faN"; +export { definition as faNairaSign } from "@fortawesome/free-solid-svg-icons/faNairaSign"; +export { definition as faNavicon } from "@fortawesome/free-solid-svg-icons/faNavicon"; +export { definition as faNetworkWired } from "@fortawesome/free-solid-svg-icons/faNetworkWired"; +export { definition as faNeuter } from "@fortawesome/free-solid-svg-icons/faNeuter"; +export { definition as faNewspaper } from "@fortawesome/free-solid-svg-icons/faNewspaper"; +export { definition as faNotEqual } from "@fortawesome/free-solid-svg-icons/faNotEqual"; +export { definition as faNotdef } from "@fortawesome/free-solid-svg-icons/faNotdef"; +export { definition as faNoteSticky } from "@fortawesome/free-solid-svg-icons/faNoteSticky"; +export { definition as faNotesMedical } from "@fortawesome/free-solid-svg-icons/faNotesMedical"; +export { definition as faO } from "@fortawesome/free-solid-svg-icons/faO"; +export { definition as faObjectGroup } from "@fortawesome/free-solid-svg-icons/faObjectGroup"; +export { definition as faObjectUngroup } from "@fortawesome/free-solid-svg-icons/faObjectUngroup"; +export { definition as faOilCan } from "@fortawesome/free-solid-svg-icons/faOilCan"; +export { definition as faOilWell } from "@fortawesome/free-solid-svg-icons/faOilWell"; +export { definition as faOm } from "@fortawesome/free-solid-svg-icons/faOm"; +export { definition as faOtter } from "@fortawesome/free-solid-svg-icons/faOtter"; +export { definition as faOutdent } from "@fortawesome/free-solid-svg-icons/faOutdent"; +export { definition as faP } from "@fortawesome/free-solid-svg-icons/faP"; +export { definition as faPager } from "@fortawesome/free-solid-svg-icons/faPager"; +export { definition as faPaintRoller } from "@fortawesome/free-solid-svg-icons/faPaintRoller"; +export { definition as faPaintbrush } from "@fortawesome/free-solid-svg-icons/faPaintbrush"; +export { definition as faPalette } from "@fortawesome/free-solid-svg-icons/faPalette"; +export { definition as faPallet } from "@fortawesome/free-solid-svg-icons/faPallet"; +export { definition as faPanorama } from "@fortawesome/free-solid-svg-icons/faPanorama"; +export { definition as faPaperPlane } from "@fortawesome/free-solid-svg-icons/faPaperPlane"; +export { definition as faPaperclip } from "@fortawesome/free-solid-svg-icons/faPaperclip"; +export { definition as faParachuteBox } from "@fortawesome/free-solid-svg-icons/faParachuteBox"; +export { definition as faParagraph } from "@fortawesome/free-solid-svg-icons/faParagraph"; +export { definition as faParking } from "@fortawesome/free-solid-svg-icons/faParking"; +export { definition as faPassport } from "@fortawesome/free-solid-svg-icons/faPassport"; +export { definition as faPastafarianism } from "@fortawesome/free-solid-svg-icons/faPastafarianism"; +export { definition as faPaste } from "@fortawesome/free-solid-svg-icons/faPaste"; +export { definition as faPause } from "@fortawesome/free-solid-svg-icons/faPause"; +export { definition as faPauseCircle } from "@fortawesome/free-solid-svg-icons/faPauseCircle"; +export { definition as faPaw } from "@fortawesome/free-solid-svg-icons/faPaw"; +export { definition as faPeace } from "@fortawesome/free-solid-svg-icons/faPeace"; +export { definition as faPen } from "@fortawesome/free-solid-svg-icons/faPen"; +export { definition as faPenAlt } from "@fortawesome/free-solid-svg-icons/faPenAlt"; +export { definition as faPenClip } from "@fortawesome/free-solid-svg-icons/faPenClip"; +export { definition as faPenFancy } from "@fortawesome/free-solid-svg-icons/faPenFancy"; +export { definition as faPenNib } from "@fortawesome/free-solid-svg-icons/faPenNib"; +export { definition as faPenRuler } from "@fortawesome/free-solid-svg-icons/faPenRuler"; +export { definition as faPenSquare } from "@fortawesome/free-solid-svg-icons/faPenSquare"; +export { definition as faPenToSquare } from "@fortawesome/free-solid-svg-icons/faPenToSquare"; +export { definition as faPencil } from "@fortawesome/free-solid-svg-icons/faPencil"; +export { definition as faPencilAlt } from "@fortawesome/free-solid-svg-icons/faPencilAlt"; +export { definition as faPencilRuler } from "@fortawesome/free-solid-svg-icons/faPencilRuler"; +export { definition as faPencilSquare } from "@fortawesome/free-solid-svg-icons/faPencilSquare"; +export { definition as faPeopleArrows } from "@fortawesome/free-solid-svg-icons/faPeopleArrows"; +export { definition as faPeopleArrowsLeftRight } from "@fortawesome/free-solid-svg-icons/faPeopleArrowsLeftRight"; +export { definition as faPeopleCarry } from "@fortawesome/free-solid-svg-icons/faPeopleCarry"; +export { definition as faPeopleCarryBox } from "@fortawesome/free-solid-svg-icons/faPeopleCarryBox"; +export { definition as faPeopleGroup } from "@fortawesome/free-solid-svg-icons/faPeopleGroup"; +export { definition as faPeopleLine } from "@fortawesome/free-solid-svg-icons/faPeopleLine"; +export { definition as faPeoplePulling } from "@fortawesome/free-solid-svg-icons/faPeoplePulling"; +export { definition as faPeopleRobbery } from "@fortawesome/free-solid-svg-icons/faPeopleRobbery"; +export { definition as faPeopleRoof } from "@fortawesome/free-solid-svg-icons/faPeopleRoof"; +export { definition as faPepperHot } from "@fortawesome/free-solid-svg-icons/faPepperHot"; +export { definition as faPercent } from "@fortawesome/free-solid-svg-icons/faPercent"; +export { definition as faPercentage } from "@fortawesome/free-solid-svg-icons/faPercentage"; +export { definition as faPerson } from "@fortawesome/free-solid-svg-icons/faPerson"; +export { definition as faPersonArrowDownToLine } from "@fortawesome/free-solid-svg-icons/faPersonArrowDownToLine"; +export { definition as faPersonArrowUpFromLine } from "@fortawesome/free-solid-svg-icons/faPersonArrowUpFromLine"; +export { definition as faPersonBiking } from "@fortawesome/free-solid-svg-icons/faPersonBiking"; +export { definition as faPersonBooth } from "@fortawesome/free-solid-svg-icons/faPersonBooth"; +export { definition as faPersonBreastfeeding } from "@fortawesome/free-solid-svg-icons/faPersonBreastfeeding"; +export { definition as faPersonBurst } from "@fortawesome/free-solid-svg-icons/faPersonBurst"; +export { definition as faPersonCane } from "@fortawesome/free-solid-svg-icons/faPersonCane"; +export { definition as faPersonChalkboard } from "@fortawesome/free-solid-svg-icons/faPersonChalkboard"; +export { definition as faPersonCircleCheck } from "@fortawesome/free-solid-svg-icons/faPersonCircleCheck"; +export { definition as faPersonCircleExclamation } from "@fortawesome/free-solid-svg-icons/faPersonCircleExclamation"; +export { definition as faPersonCircleMinus } from "@fortawesome/free-solid-svg-icons/faPersonCircleMinus"; +export { definition as faPersonCirclePlus } from "@fortawesome/free-solid-svg-icons/faPersonCirclePlus"; +export { definition as faPersonCircleQuestion } from "@fortawesome/free-solid-svg-icons/faPersonCircleQuestion"; +export { definition as faPersonCircleXmark } from "@fortawesome/free-solid-svg-icons/faPersonCircleXmark"; +export { definition as faPersonDigging } from "@fortawesome/free-solid-svg-icons/faPersonDigging"; +export { definition as faPersonDotsFromLine } from "@fortawesome/free-solid-svg-icons/faPersonDotsFromLine"; +export { definition as faPersonDress } from "@fortawesome/free-solid-svg-icons/faPersonDress"; +export { definition as faPersonDressBurst } from "@fortawesome/free-solid-svg-icons/faPersonDressBurst"; +export { definition as faPersonDrowning } from "@fortawesome/free-solid-svg-icons/faPersonDrowning"; +export { definition as faPersonFalling } from "@fortawesome/free-solid-svg-icons/faPersonFalling"; +export { definition as faPersonFallingBurst } from "@fortawesome/free-solid-svg-icons/faPersonFallingBurst"; +export { definition as faPersonHalfDress } from "@fortawesome/free-solid-svg-icons/faPersonHalfDress"; +export { definition as faPersonHarassing } from "@fortawesome/free-solid-svg-icons/faPersonHarassing"; +export { definition as faPersonHiking } from "@fortawesome/free-solid-svg-icons/faPersonHiking"; +export { definition as faPersonMilitaryPointing } from "@fortawesome/free-solid-svg-icons/faPersonMilitaryPointing"; +export { definition as faPersonMilitaryRifle } from "@fortawesome/free-solid-svg-icons/faPersonMilitaryRifle"; +export { definition as faPersonMilitaryToPerson } from "@fortawesome/free-solid-svg-icons/faPersonMilitaryToPerson"; +export { definition as faPersonPraying } from "@fortawesome/free-solid-svg-icons/faPersonPraying"; +export { definition as faPersonPregnant } from "@fortawesome/free-solid-svg-icons/faPersonPregnant"; +export { definition as faPersonRays } from "@fortawesome/free-solid-svg-icons/faPersonRays"; +export { definition as faPersonRifle } from "@fortawesome/free-solid-svg-icons/faPersonRifle"; +export { definition as faPersonRunning } from "@fortawesome/free-solid-svg-icons/faPersonRunning"; +export { definition as faPersonShelter } from "@fortawesome/free-solid-svg-icons/faPersonShelter"; +export { definition as faPersonSkating } from "@fortawesome/free-solid-svg-icons/faPersonSkating"; +export { definition as faPersonSkiing } from "@fortawesome/free-solid-svg-icons/faPersonSkiing"; +export { definition as faPersonSkiingNordic } from "@fortawesome/free-solid-svg-icons/faPersonSkiingNordic"; +export { definition as faPersonSnowboarding } from "@fortawesome/free-solid-svg-icons/faPersonSnowboarding"; +export { definition as faPersonSwimming } from "@fortawesome/free-solid-svg-icons/faPersonSwimming"; +export { definition as faPersonThroughWindow } from "@fortawesome/free-solid-svg-icons/faPersonThroughWindow"; +export { definition as faPersonWalking } from "@fortawesome/free-solid-svg-icons/faPersonWalking"; +export { definition as faPersonWalkingArrowLoopLeft } from "@fortawesome/free-solid-svg-icons/faPersonWalkingArrowLoopLeft"; +export { definition as faPersonWalkingArrowRight } from "@fortawesome/free-solid-svg-icons/faPersonWalkingArrowRight"; +export { definition as faPersonWalkingDashedLineArrowRight } from "@fortawesome/free-solid-svg-icons/faPersonWalkingDashedLineArrowRight"; +export { definition as faPersonWalkingLuggage } from "@fortawesome/free-solid-svg-icons/faPersonWalkingLuggage"; +export { definition as faPersonWalkingWithCane } from "@fortawesome/free-solid-svg-icons/faPersonWalkingWithCane"; +export { definition as faPesetaSign } from "@fortawesome/free-solid-svg-icons/faPesetaSign"; +export { definition as faPesoSign } from "@fortawesome/free-solid-svg-icons/faPesoSign"; +export { definition as faPhone } from "@fortawesome/free-solid-svg-icons/faPhone"; +export { definition as faPhoneAlt } from "@fortawesome/free-solid-svg-icons/faPhoneAlt"; +export { definition as faPhoneFlip } from "@fortawesome/free-solid-svg-icons/faPhoneFlip"; +export { definition as faPhoneSlash } from "@fortawesome/free-solid-svg-icons/faPhoneSlash"; +export { definition as faPhoneSquare } from "@fortawesome/free-solid-svg-icons/faPhoneSquare"; +export { definition as faPhoneSquareAlt } from "@fortawesome/free-solid-svg-icons/faPhoneSquareAlt"; +export { definition as faPhoneVolume } from "@fortawesome/free-solid-svg-icons/faPhoneVolume"; +export { definition as faPhotoFilm } from "@fortawesome/free-solid-svg-icons/faPhotoFilm"; +export { definition as faPhotoVideo } from "@fortawesome/free-solid-svg-icons/faPhotoVideo"; +export { definition as faPieChart } from "@fortawesome/free-solid-svg-icons/faPieChart"; +export { definition as faPiggyBank } from "@fortawesome/free-solid-svg-icons/faPiggyBank"; +export { definition as faPills } from "@fortawesome/free-solid-svg-icons/faPills"; +export { definition as faPingPongPaddleBall } from "@fortawesome/free-solid-svg-icons/faPingPongPaddleBall"; +export { definition as faPizzaSlice } from "@fortawesome/free-solid-svg-icons/faPizzaSlice"; +export { definition as faPlaceOfWorship } from "@fortawesome/free-solid-svg-icons/faPlaceOfWorship"; +export { definition as faPlane } from "@fortawesome/free-solid-svg-icons/faPlane"; +export { definition as faPlaneArrival } from "@fortawesome/free-solid-svg-icons/faPlaneArrival"; +export { definition as faPlaneCircleCheck } from "@fortawesome/free-solid-svg-icons/faPlaneCircleCheck"; +export { definition as faPlaneCircleExclamation } from "@fortawesome/free-solid-svg-icons/faPlaneCircleExclamation"; +export { definition as faPlaneCircleXmark } from "@fortawesome/free-solid-svg-icons/faPlaneCircleXmark"; +export { definition as faPlaneDeparture } from "@fortawesome/free-solid-svg-icons/faPlaneDeparture"; +export { definition as faPlaneLock } from "@fortawesome/free-solid-svg-icons/faPlaneLock"; +export { definition as faPlaneSlash } from "@fortawesome/free-solid-svg-icons/faPlaneSlash"; +export { definition as faPlaneUp } from "@fortawesome/free-solid-svg-icons/faPlaneUp"; +export { definition as faPlantWilt } from "@fortawesome/free-solid-svg-icons/faPlantWilt"; +export { definition as faPlateWheat } from "@fortawesome/free-solid-svg-icons/faPlateWheat"; +export { definition as faPlay } from "@fortawesome/free-solid-svg-icons/faPlay"; +export { definition as faPlayCircle } from "@fortawesome/free-solid-svg-icons/faPlayCircle"; +export { definition as faPlug } from "@fortawesome/free-solid-svg-icons/faPlug"; +export { definition as faPlugCircleBolt } from "@fortawesome/free-solid-svg-icons/faPlugCircleBolt"; +export { definition as faPlugCircleCheck } from "@fortawesome/free-solid-svg-icons/faPlugCircleCheck"; +export { definition as faPlugCircleExclamation } from "@fortawesome/free-solid-svg-icons/faPlugCircleExclamation"; +export { definition as faPlugCircleMinus } from "@fortawesome/free-solid-svg-icons/faPlugCircleMinus"; +export { definition as faPlugCirclePlus } from "@fortawesome/free-solid-svg-icons/faPlugCirclePlus"; +export { definition as faPlugCircleXmark } from "@fortawesome/free-solid-svg-icons/faPlugCircleXmark"; +export { definition as faPlus } from "@fortawesome/free-solid-svg-icons/faPlus"; +export { definition as faPlusCircle } from "@fortawesome/free-solid-svg-icons/faPlusCircle"; +export { definition as faPlusMinus } from "@fortawesome/free-solid-svg-icons/faPlusMinus"; +export { definition as faPlusSquare } from "@fortawesome/free-solid-svg-icons/faPlusSquare"; +export { definition as faPodcast } from "@fortawesome/free-solid-svg-icons/faPodcast"; +export { definition as faPoll } from "@fortawesome/free-solid-svg-icons/faPoll"; +export { definition as faPollH } from "@fortawesome/free-solid-svg-icons/faPollH"; +export { definition as faPoo } from "@fortawesome/free-solid-svg-icons/faPoo"; +export { definition as faPooBolt } from "@fortawesome/free-solid-svg-icons/faPooBolt"; +export { definition as faPooStorm } from "@fortawesome/free-solid-svg-icons/faPooStorm"; +export { definition as faPoop } from "@fortawesome/free-solid-svg-icons/faPoop"; +export { definition as faPortrait } from "@fortawesome/free-solid-svg-icons/faPortrait"; +export { definition as faPoundSign } from "@fortawesome/free-solid-svg-icons/faPoundSign"; +export { definition as faPowerOff } from "@fortawesome/free-solid-svg-icons/faPowerOff"; +export { definition as faPray } from "@fortawesome/free-solid-svg-icons/faPray"; +export { definition as faPrayingHands } from "@fortawesome/free-solid-svg-icons/faPrayingHands"; +export { definition as faPrescription } from "@fortawesome/free-solid-svg-icons/faPrescription"; +export { definition as faPrescriptionBottle } from "@fortawesome/free-solid-svg-icons/faPrescriptionBottle"; +export { definition as faPrescriptionBottleAlt } from "@fortawesome/free-solid-svg-icons/faPrescriptionBottleAlt"; +export { definition as faPrescriptionBottleMedical } from "@fortawesome/free-solid-svg-icons/faPrescriptionBottleMedical"; +export { definition as faPrint } from "@fortawesome/free-solid-svg-icons/faPrint"; +export { definition as faProcedures } from "@fortawesome/free-solid-svg-icons/faProcedures"; +export { definition as faProjectDiagram } from "@fortawesome/free-solid-svg-icons/faProjectDiagram"; +export { definition as faPumpMedical } from "@fortawesome/free-solid-svg-icons/faPumpMedical"; +export { definition as faPumpSoap } from "@fortawesome/free-solid-svg-icons/faPumpSoap"; +export { definition as faPuzzlePiece } from "@fortawesome/free-solid-svg-icons/faPuzzlePiece"; +export { definition as faQ } from "@fortawesome/free-solid-svg-icons/faQ"; +export { definition as faQrcode } from "@fortawesome/free-solid-svg-icons/faQrcode"; +export { definition as faQuestion } from "@fortawesome/free-solid-svg-icons/faQuestion"; +export { definition as faQuestionCircle } from "@fortawesome/free-solid-svg-icons/faQuestionCircle"; +export { definition as faQuidditch } from "@fortawesome/free-solid-svg-icons/faQuidditch"; +export { definition as faQuidditchBroomBall } from "@fortawesome/free-solid-svg-icons/faQuidditchBroomBall"; +export { definition as faQuoteLeft } from "@fortawesome/free-solid-svg-icons/faQuoteLeft"; +export { definition as faQuoteLeftAlt } from "@fortawesome/free-solid-svg-icons/faQuoteLeftAlt"; +export { definition as faQuoteRight } from "@fortawesome/free-solid-svg-icons/faQuoteRight"; +export { definition as faQuoteRightAlt } from "@fortawesome/free-solid-svg-icons/faQuoteRightAlt"; +export { definition as faQuran } from "@fortawesome/free-solid-svg-icons/faQuran"; +export { definition as faR } from "@fortawesome/free-solid-svg-icons/faR"; +export { definition as faRadiation } from "@fortawesome/free-solid-svg-icons/faRadiation"; +export { definition as faRadiationAlt } from "@fortawesome/free-solid-svg-icons/faRadiationAlt"; +export { definition as faRadio } from "@fortawesome/free-solid-svg-icons/faRadio"; +export { definition as faRainbow } from "@fortawesome/free-solid-svg-icons/faRainbow"; +export { definition as faRandom } from "@fortawesome/free-solid-svg-icons/faRandom"; +export { definition as faRankingStar } from "@fortawesome/free-solid-svg-icons/faRankingStar"; +export { definition as faReceipt } from "@fortawesome/free-solid-svg-icons/faReceipt"; +export { definition as faRecordVinyl } from "@fortawesome/free-solid-svg-icons/faRecordVinyl"; +export { definition as faRectangleAd } from "@fortawesome/free-solid-svg-icons/faRectangleAd"; +export { definition as faRectangleList } from "@fortawesome/free-solid-svg-icons/faRectangleList"; +export { definition as faRectangleTimes } from "@fortawesome/free-solid-svg-icons/faRectangleTimes"; +export { definition as faRectangleXmark } from "@fortawesome/free-solid-svg-icons/faRectangleXmark"; +export { definition as faRecycle } from "@fortawesome/free-solid-svg-icons/faRecycle"; +export { definition as faRedo } from "@fortawesome/free-solid-svg-icons/faRedo"; +export { definition as faRedoAlt } from "@fortawesome/free-solid-svg-icons/faRedoAlt"; +export { definition as faRefresh } from "@fortawesome/free-solid-svg-icons/faRefresh"; +export { definition as faRegistered } from "@fortawesome/free-solid-svg-icons/faRegistered"; +export { definition as faRemove } from "@fortawesome/free-solid-svg-icons/faRemove"; +export { definition as faRemoveFormat } from "@fortawesome/free-solid-svg-icons/faRemoveFormat"; +export { definition as faReorder } from "@fortawesome/free-solid-svg-icons/faReorder"; +export { definition as faRepeat } from "@fortawesome/free-solid-svg-icons/faRepeat"; +export { definition as faReply } from "@fortawesome/free-solid-svg-icons/faReply"; +export { definition as faReplyAll } from "@fortawesome/free-solid-svg-icons/faReplyAll"; +export { definition as faRepublican } from "@fortawesome/free-solid-svg-icons/faRepublican"; +export { definition as faRestroom } from "@fortawesome/free-solid-svg-icons/faRestroom"; +export { definition as faRetweet } from "@fortawesome/free-solid-svg-icons/faRetweet"; +export { definition as faRibbon } from "@fortawesome/free-solid-svg-icons/faRibbon"; +export { definition as faRightFromBracket } from "@fortawesome/free-solid-svg-icons/faRightFromBracket"; +export { definition as faRightLeft } from "@fortawesome/free-solid-svg-icons/faRightLeft"; +export { definition as faRightLong } from "@fortawesome/free-solid-svg-icons/faRightLong"; +export { definition as faRightToBracket } from "@fortawesome/free-solid-svg-icons/faRightToBracket"; +export { definition as faRing } from "@fortawesome/free-solid-svg-icons/faRing"; +export { definition as faRmb } from "@fortawesome/free-solid-svg-icons/faRmb"; +export { definition as faRoad } from "@fortawesome/free-solid-svg-icons/faRoad"; +export { definition as faRoadBarrier } from "@fortawesome/free-solid-svg-icons/faRoadBarrier"; +export { definition as faRoadBridge } from "@fortawesome/free-solid-svg-icons/faRoadBridge"; +export { definition as faRoadCircleCheck } from "@fortawesome/free-solid-svg-icons/faRoadCircleCheck"; +export { definition as faRoadCircleExclamation } from "@fortawesome/free-solid-svg-icons/faRoadCircleExclamation"; +export { definition as faRoadCircleXmark } from "@fortawesome/free-solid-svg-icons/faRoadCircleXmark"; +export { definition as faRoadLock } from "@fortawesome/free-solid-svg-icons/faRoadLock"; +export { definition as faRoadSpikes } from "@fortawesome/free-solid-svg-icons/faRoadSpikes"; +export { definition as faRobot } from "@fortawesome/free-solid-svg-icons/faRobot"; +export { definition as faRocket } from "@fortawesome/free-solid-svg-icons/faRocket"; +export { definition as faRodAsclepius } from "@fortawesome/free-solid-svg-icons/faRodAsclepius"; +export { definition as faRodSnake } from "@fortawesome/free-solid-svg-icons/faRodSnake"; +export { definition as faRotate } from "@fortawesome/free-solid-svg-icons/faRotate"; +export { definition as faRotateBack } from "@fortawesome/free-solid-svg-icons/faRotateBack"; +export { definition as faRotateBackward } from "@fortawesome/free-solid-svg-icons/faRotateBackward"; +export { definition as faRotateForward } from "@fortawesome/free-solid-svg-icons/faRotateForward"; +export { definition as faRotateLeft } from "@fortawesome/free-solid-svg-icons/faRotateLeft"; +export { definition as faRotateRight } from "@fortawesome/free-solid-svg-icons/faRotateRight"; +export { definition as faRouble } from "@fortawesome/free-solid-svg-icons/faRouble"; +export { definition as faRoute } from "@fortawesome/free-solid-svg-icons/faRoute"; +export { definition as faRss } from "@fortawesome/free-solid-svg-icons/faRss"; +export { definition as faRssSquare } from "@fortawesome/free-solid-svg-icons/faRssSquare"; +export { definition as faRub } from "@fortawesome/free-solid-svg-icons/faRub"; +export { definition as faRuble } from "@fortawesome/free-solid-svg-icons/faRuble"; +export { definition as faRubleSign } from "@fortawesome/free-solid-svg-icons/faRubleSign"; +export { definition as faRug } from "@fortawesome/free-solid-svg-icons/faRug"; +export { definition as faRuler } from "@fortawesome/free-solid-svg-icons/faRuler"; +export { definition as faRulerCombined } from "@fortawesome/free-solid-svg-icons/faRulerCombined"; +export { definition as faRulerHorizontal } from "@fortawesome/free-solid-svg-icons/faRulerHorizontal"; +export { definition as faRulerVertical } from "@fortawesome/free-solid-svg-icons/faRulerVertical"; +export { definition as faRunning } from "@fortawesome/free-solid-svg-icons/faRunning"; +export { definition as faRupee } from "@fortawesome/free-solid-svg-icons/faRupee"; +export { definition as faRupeeSign } from "@fortawesome/free-solid-svg-icons/faRupeeSign"; +export { definition as faRupiahSign } from "@fortawesome/free-solid-svg-icons/faRupiahSign"; +export { definition as faS } from "@fortawesome/free-solid-svg-icons/faS"; +export { definition as faSackDollar } from "@fortawesome/free-solid-svg-icons/faSackDollar"; +export { definition as faSackXmark } from "@fortawesome/free-solid-svg-icons/faSackXmark"; +export { definition as faSadCry } from "@fortawesome/free-solid-svg-icons/faSadCry"; +export { definition as faSadTear } from "@fortawesome/free-solid-svg-icons/faSadTear"; +export { definition as faSailboat } from "@fortawesome/free-solid-svg-icons/faSailboat"; +export { definition as faSatellite } from "@fortawesome/free-solid-svg-icons/faSatellite"; +export { definition as faSatelliteDish } from "@fortawesome/free-solid-svg-icons/faSatelliteDish"; +export { definition as faSave } from "@fortawesome/free-solid-svg-icons/faSave"; +export { definition as faScaleBalanced } from "@fortawesome/free-solid-svg-icons/faScaleBalanced"; +export { definition as faScaleUnbalanced } from "@fortawesome/free-solid-svg-icons/faScaleUnbalanced"; +export { definition as faScaleUnbalancedFlip } from "@fortawesome/free-solid-svg-icons/faScaleUnbalancedFlip"; +export { definition as faSchool } from "@fortawesome/free-solid-svg-icons/faSchool"; +export { definition as faSchoolCircleCheck } from "@fortawesome/free-solid-svg-icons/faSchoolCircleCheck"; +export { definition as faSchoolCircleExclamation } from "@fortawesome/free-solid-svg-icons/faSchoolCircleExclamation"; +export { definition as faSchoolCircleXmark } from "@fortawesome/free-solid-svg-icons/faSchoolCircleXmark"; +export { definition as faSchoolFlag } from "@fortawesome/free-solid-svg-icons/faSchoolFlag"; +export { definition as faSchoolLock } from "@fortawesome/free-solid-svg-icons/faSchoolLock"; +export { definition as faScissors } from "@fortawesome/free-solid-svg-icons/faScissors"; +export { definition as faScrewdriver } from "@fortawesome/free-solid-svg-icons/faScrewdriver"; +export { definition as faScrewdriverWrench } from "@fortawesome/free-solid-svg-icons/faScrewdriverWrench"; +export { definition as faScroll } from "@fortawesome/free-solid-svg-icons/faScroll"; +export { definition as faScrollTorah } from "@fortawesome/free-solid-svg-icons/faScrollTorah"; +export { definition as faSdCard } from "@fortawesome/free-solid-svg-icons/faSdCard"; +export { definition as faSearch } from "@fortawesome/free-solid-svg-icons/faSearch"; +export { definition as faSearchDollar } from "@fortawesome/free-solid-svg-icons/faSearchDollar"; +export { definition as faSearchLocation } from "@fortawesome/free-solid-svg-icons/faSearchLocation"; +export { definition as faSearchMinus } from "@fortawesome/free-solid-svg-icons/faSearchMinus"; +export { definition as faSearchPlus } from "@fortawesome/free-solid-svg-icons/faSearchPlus"; +export { definition as faSection } from "@fortawesome/free-solid-svg-icons/faSection"; +export { definition as faSeedling } from "@fortawesome/free-solid-svg-icons/faSeedling"; +export { definition as faServer } from "@fortawesome/free-solid-svg-icons/faServer"; +export { definition as faShapes } from "@fortawesome/free-solid-svg-icons/faShapes"; +export { definition as faShare } from "@fortawesome/free-solid-svg-icons/faShare"; +export { definition as faShareAlt } from "@fortawesome/free-solid-svg-icons/faShareAlt"; +export { definition as faShareAltSquare } from "@fortawesome/free-solid-svg-icons/faShareAltSquare"; +export { definition as faShareFromSquare } from "@fortawesome/free-solid-svg-icons/faShareFromSquare"; +export { definition as faShareNodes } from "@fortawesome/free-solid-svg-icons/faShareNodes"; +export { definition as faShareSquare } from "@fortawesome/free-solid-svg-icons/faShareSquare"; +export { definition as faSheetPlastic } from "@fortawesome/free-solid-svg-icons/faSheetPlastic"; +export { definition as faShekel } from "@fortawesome/free-solid-svg-icons/faShekel"; +export { definition as faShekelSign } from "@fortawesome/free-solid-svg-icons/faShekelSign"; +export { definition as faSheqel } from "@fortawesome/free-solid-svg-icons/faSheqel"; +export { definition as faSheqelSign } from "@fortawesome/free-solid-svg-icons/faSheqelSign"; +export { definition as faShield } from "@fortawesome/free-solid-svg-icons/faShield"; +export { definition as faShieldAlt } from "@fortawesome/free-solid-svg-icons/faShieldAlt"; +export { definition as faShieldBlank } from "@fortawesome/free-solid-svg-icons/faShieldBlank"; +export { definition as faShieldCat } from "@fortawesome/free-solid-svg-icons/faShieldCat"; +export { definition as faShieldDog } from "@fortawesome/free-solid-svg-icons/faShieldDog"; +export { definition as faShieldHalved } from "@fortawesome/free-solid-svg-icons/faShieldHalved"; +export { definition as faShieldHeart } from "@fortawesome/free-solid-svg-icons/faShieldHeart"; +export { definition as faShieldVirus } from "@fortawesome/free-solid-svg-icons/faShieldVirus"; +export { definition as faShip } from "@fortawesome/free-solid-svg-icons/faShip"; +export { definition as faShippingFast } from "@fortawesome/free-solid-svg-icons/faShippingFast"; +export { definition as faShirt } from "@fortawesome/free-solid-svg-icons/faShirt"; +export { definition as faShoePrints } from "@fortawesome/free-solid-svg-icons/faShoePrints"; +export { definition as faShop } from "@fortawesome/free-solid-svg-icons/faShop"; +export { definition as faShopLock } from "@fortawesome/free-solid-svg-icons/faShopLock"; +export { definition as faShopSlash } from "@fortawesome/free-solid-svg-icons/faShopSlash"; +export { definition as faShoppingBag } from "@fortawesome/free-solid-svg-icons/faShoppingBag"; +export { definition as faShoppingBasket } from "@fortawesome/free-solid-svg-icons/faShoppingBasket"; +export { definition as faShoppingCart } from "@fortawesome/free-solid-svg-icons/faShoppingCart"; +export { definition as faShower } from "@fortawesome/free-solid-svg-icons/faShower"; +export { definition as faShrimp } from "@fortawesome/free-solid-svg-icons/faShrimp"; +export { definition as faShuffle } from "@fortawesome/free-solid-svg-icons/faShuffle"; +export { definition as faShuttleSpace } from "@fortawesome/free-solid-svg-icons/faShuttleSpace"; +export { definition as faShuttleVan } from "@fortawesome/free-solid-svg-icons/faShuttleVan"; +export { definition as faSign } from "@fortawesome/free-solid-svg-icons/faSign"; +export { definition as faSignHanging } from "@fortawesome/free-solid-svg-icons/faSignHanging"; +export { definition as faSignIn } from "@fortawesome/free-solid-svg-icons/faSignIn"; +export { definition as faSignInAlt } from "@fortawesome/free-solid-svg-icons/faSignInAlt"; +export { definition as faSignLanguage } from "@fortawesome/free-solid-svg-icons/faSignLanguage"; +export { definition as faSignOut } from "@fortawesome/free-solid-svg-icons/faSignOut"; +export { definition as faSignOutAlt } from "@fortawesome/free-solid-svg-icons/faSignOutAlt"; +export { definition as faSignal } from "@fortawesome/free-solid-svg-icons/faSignal"; +export { definition as faSignal5 } from "@fortawesome/free-solid-svg-icons/faSignal5"; +export { definition as faSignalPerfect } from "@fortawesome/free-solid-svg-icons/faSignalPerfect"; +export { definition as faSignature } from "@fortawesome/free-solid-svg-icons/faSignature"; +export { definition as faSigning } from "@fortawesome/free-solid-svg-icons/faSigning"; +export { definition as faSignsPost } from "@fortawesome/free-solid-svg-icons/faSignsPost"; +export { definition as faSimCard } from "@fortawesome/free-solid-svg-icons/faSimCard"; +export { definition as faSink } from "@fortawesome/free-solid-svg-icons/faSink"; +export { definition as faSitemap } from "@fortawesome/free-solid-svg-icons/faSitemap"; +export { definition as faSkating } from "@fortawesome/free-solid-svg-icons/faSkating"; +export { definition as faSkiing } from "@fortawesome/free-solid-svg-icons/faSkiing"; +export { definition as faSkiingNordic } from "@fortawesome/free-solid-svg-icons/faSkiingNordic"; +export { definition as faSkull } from "@fortawesome/free-solid-svg-icons/faSkull"; +export { definition as faSkullCrossbones } from "@fortawesome/free-solid-svg-icons/faSkullCrossbones"; +export { definition as faSlash } from "@fortawesome/free-solid-svg-icons/faSlash"; +export { definition as faSleigh } from "@fortawesome/free-solid-svg-icons/faSleigh"; +export { definition as faSliders } from "@fortawesome/free-solid-svg-icons/faSliders"; +export { definition as faSlidersH } from "@fortawesome/free-solid-svg-icons/faSlidersH"; +export { definition as faSmile } from "@fortawesome/free-solid-svg-icons/faSmile"; +export { definition as faSmileBeam } from "@fortawesome/free-solid-svg-icons/faSmileBeam"; +export { definition as faSmileWink } from "@fortawesome/free-solid-svg-icons/faSmileWink"; +export { definition as faSmog } from "@fortawesome/free-solid-svg-icons/faSmog"; +export { definition as faSmoking } from "@fortawesome/free-solid-svg-icons/faSmoking"; +export { definition as faSmokingBan } from "@fortawesome/free-solid-svg-icons/faSmokingBan"; +export { definition as faSms } from "@fortawesome/free-solid-svg-icons/faSms"; +export { definition as faSnowboarding } from "@fortawesome/free-solid-svg-icons/faSnowboarding"; +export { definition as faSnowflake } from "@fortawesome/free-solid-svg-icons/faSnowflake"; +export { definition as faSnowman } from "@fortawesome/free-solid-svg-icons/faSnowman"; +export { definition as faSnowplow } from "@fortawesome/free-solid-svg-icons/faSnowplow"; +export { definition as faSoap } from "@fortawesome/free-solid-svg-icons/faSoap"; +export { definition as faSoccerBall } from "@fortawesome/free-solid-svg-icons/faSoccerBall"; +export { definition as faSocks } from "@fortawesome/free-solid-svg-icons/faSocks"; +export { definition as faSolarPanel } from "@fortawesome/free-solid-svg-icons/faSolarPanel"; +export { definition as faSort } from "@fortawesome/free-solid-svg-icons/faSort"; +export { definition as faSortAlphaAsc } from "@fortawesome/free-solid-svg-icons/faSortAlphaAsc"; +export { definition as faSortAlphaDesc } from "@fortawesome/free-solid-svg-icons/faSortAlphaDesc"; +export { definition as faSortAlphaDown } from "@fortawesome/free-solid-svg-icons/faSortAlphaDown"; +export { definition as faSortAlphaDownAlt } from "@fortawesome/free-solid-svg-icons/faSortAlphaDownAlt"; +export { definition as faSortAlphaUp } from "@fortawesome/free-solid-svg-icons/faSortAlphaUp"; +export { definition as faSortAlphaUpAlt } from "@fortawesome/free-solid-svg-icons/faSortAlphaUpAlt"; +export { definition as faSortAmountAsc } from "@fortawesome/free-solid-svg-icons/faSortAmountAsc"; +export { definition as faSortAmountDesc } from "@fortawesome/free-solid-svg-icons/faSortAmountDesc"; +export { definition as faSortAmountDown } from "@fortawesome/free-solid-svg-icons/faSortAmountDown"; +export { definition as faSortAmountDownAlt } from "@fortawesome/free-solid-svg-icons/faSortAmountDownAlt"; +export { definition as faSortAmountUp } from "@fortawesome/free-solid-svg-icons/faSortAmountUp"; +export { definition as faSortAmountUpAlt } from "@fortawesome/free-solid-svg-icons/faSortAmountUpAlt"; +export { definition as faSortAsc } from "@fortawesome/free-solid-svg-icons/faSortAsc"; +export { definition as faSortDesc } from "@fortawesome/free-solid-svg-icons/faSortDesc"; +export { definition as faSortDown } from "@fortawesome/free-solid-svg-icons/faSortDown"; +export { definition as faSortNumericAsc } from "@fortawesome/free-solid-svg-icons/faSortNumericAsc"; +export { definition as faSortNumericDesc } from "@fortawesome/free-solid-svg-icons/faSortNumericDesc"; +export { definition as faSortNumericDown } from "@fortawesome/free-solid-svg-icons/faSortNumericDown"; +export { definition as faSortNumericDownAlt } from "@fortawesome/free-solid-svg-icons/faSortNumericDownAlt"; +export { definition as faSortNumericUp } from "@fortawesome/free-solid-svg-icons/faSortNumericUp"; +export { definition as faSortNumericUpAlt } from "@fortawesome/free-solid-svg-icons/faSortNumericUpAlt"; +export { definition as faSortUp } from "@fortawesome/free-solid-svg-icons/faSortUp"; +export { definition as faSpa } from "@fortawesome/free-solid-svg-icons/faSpa"; +export { definition as faSpaceShuttle } from "@fortawesome/free-solid-svg-icons/faSpaceShuttle"; +export { definition as faSpaghettiMonsterFlying } from "@fortawesome/free-solid-svg-icons/faSpaghettiMonsterFlying"; +export { definition as faSpellCheck } from "@fortawesome/free-solid-svg-icons/faSpellCheck"; +export { definition as faSpider } from "@fortawesome/free-solid-svg-icons/faSpider"; +export { definition as faSpinner } from "@fortawesome/free-solid-svg-icons/faSpinner"; +export { definition as faSplotch } from "@fortawesome/free-solid-svg-icons/faSplotch"; +export { definition as faSpoon } from "@fortawesome/free-solid-svg-icons/faSpoon"; +export { definition as faSprayCan } from "@fortawesome/free-solid-svg-icons/faSprayCan"; +export { definition as faSprayCanSparkles } from "@fortawesome/free-solid-svg-icons/faSprayCanSparkles"; +export { definition as faSprout } from "@fortawesome/free-solid-svg-icons/faSprout"; +export { definition as faSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareArrowUpRight } from "@fortawesome/free-solid-svg-icons/faSquareArrowUpRight"; +export { definition as faSquareBinary } from "@fortawesome/free-solid-svg-icons/faSquareBinary"; +export { definition as faSquareCaretDown } from "@fortawesome/free-solid-svg-icons/faSquareCaretDown"; +export { definition as faSquareCaretLeft } from "@fortawesome/free-solid-svg-icons/faSquareCaretLeft"; +export { definition as faSquareCaretRight } from "@fortawesome/free-solid-svg-icons/faSquareCaretRight"; +export { definition as faSquareCaretUp } from "@fortawesome/free-solid-svg-icons/faSquareCaretUp"; +export { definition as faSquareCheck } from "@fortawesome/free-solid-svg-icons/faSquareCheck"; +export { definition as faSquareEnvelope } from "@fortawesome/free-solid-svg-icons/faSquareEnvelope"; +export { definition as faSquareFull } from "@fortawesome/free-solid-svg-icons/faSquareFull"; +export { definition as faSquareH } from "@fortawesome/free-solid-svg-icons/faSquareH"; +export { definition as faSquareMinus } from "@fortawesome/free-solid-svg-icons/faSquareMinus"; +export { definition as faSquareNfi } from "@fortawesome/free-solid-svg-icons/faSquareNfi"; +export { definition as faSquareParking } from "@fortawesome/free-solid-svg-icons/faSquareParking"; +export { definition as faSquarePen } from "@fortawesome/free-solid-svg-icons/faSquarePen"; +export { definition as faSquarePersonConfined } from "@fortawesome/free-solid-svg-icons/faSquarePersonConfined"; +export { definition as faSquarePhone } from "@fortawesome/free-solid-svg-icons/faSquarePhone"; +export { definition as faSquarePhoneFlip } from "@fortawesome/free-solid-svg-icons/faSquarePhoneFlip"; +export { definition as faSquarePlus } from "@fortawesome/free-solid-svg-icons/faSquarePlus"; +export { definition as faSquarePollHorizontal } from "@fortawesome/free-solid-svg-icons/faSquarePollHorizontal"; +export { definition as faSquarePollVertical } from "@fortawesome/free-solid-svg-icons/faSquarePollVertical"; +export { definition as faSquareRootAlt } from "@fortawesome/free-solid-svg-icons/faSquareRootAlt"; +export { definition as faSquareRootVariable } from "@fortawesome/free-solid-svg-icons/faSquareRootVariable"; +export { definition as faSquareRss } from "@fortawesome/free-solid-svg-icons/faSquareRss"; +export { definition as faSquareShareNodes } from "@fortawesome/free-solid-svg-icons/faSquareShareNodes"; +export { definition as faSquareUpRight } from "@fortawesome/free-solid-svg-icons/faSquareUpRight"; +export { definition as faSquareVirus } from "@fortawesome/free-solid-svg-icons/faSquareVirus"; +export { definition as faSquareXmark } from "@fortawesome/free-solid-svg-icons/faSquareXmark"; +export { definition as faStaffAesculapius } from "@fortawesome/free-solid-svg-icons/faStaffAesculapius"; +export { definition as faStaffSnake } from "@fortawesome/free-solid-svg-icons/faStaffSnake"; +export { definition as faStairs } from "@fortawesome/free-solid-svg-icons/faStairs"; +export { definition as faStamp } from "@fortawesome/free-solid-svg-icons/faStamp"; +export { definition as faStapler } from "@fortawesome/free-solid-svg-icons/faStapler"; +export { definition as faStar } from "@fortawesome/free-solid-svg-icons/faStar"; +export { definition as faStarAndCrescent } from "@fortawesome/free-solid-svg-icons/faStarAndCrescent"; +export { definition as faStarHalf } from "@fortawesome/free-solid-svg-icons/faStarHalf"; +export { definition as faStarHalfAlt } from "@fortawesome/free-solid-svg-icons/faStarHalfAlt"; +export { definition as faStarHalfStroke } from "@fortawesome/free-solid-svg-icons/faStarHalfStroke"; +export { definition as faStarOfDavid } from "@fortawesome/free-solid-svg-icons/faStarOfDavid"; +export { definition as faStarOfLife } from "@fortawesome/free-solid-svg-icons/faStarOfLife"; +export { definition as faStepBackward } from "@fortawesome/free-solid-svg-icons/faStepBackward"; +export { definition as faStepForward } from "@fortawesome/free-solid-svg-icons/faStepForward"; +export { definition as faSterlingSign } from "@fortawesome/free-solid-svg-icons/faSterlingSign"; +export { definition as faStethoscope } from "@fortawesome/free-solid-svg-icons/faStethoscope"; +export { definition as faStickyNote } from "@fortawesome/free-solid-svg-icons/faStickyNote"; +export { definition as faStop } from "@fortawesome/free-solid-svg-icons/faStop"; +export { definition as faStopCircle } from "@fortawesome/free-solid-svg-icons/faStopCircle"; +export { definition as faStopwatch } from "@fortawesome/free-solid-svg-icons/faStopwatch"; +export { definition as faStopwatch20 } from "@fortawesome/free-solid-svg-icons/faStopwatch20"; +export { definition as faStore } from "@fortawesome/free-solid-svg-icons/faStore"; +export { definition as faStoreAlt } from "@fortawesome/free-solid-svg-icons/faStoreAlt"; +export { definition as faStoreAltSlash } from "@fortawesome/free-solid-svg-icons/faStoreAltSlash"; +export { definition as faStoreSlash } from "@fortawesome/free-solid-svg-icons/faStoreSlash"; +export { definition as faStream } from "@fortawesome/free-solid-svg-icons/faStream"; +export { definition as faStreetView } from "@fortawesome/free-solid-svg-icons/faStreetView"; +export { definition as faStrikethrough } from "@fortawesome/free-solid-svg-icons/faStrikethrough"; +export { definition as faStroopwafel } from "@fortawesome/free-solid-svg-icons/faStroopwafel"; +export { definition as faSubscript } from "@fortawesome/free-solid-svg-icons/faSubscript"; +export { definition as faSubtract } from "@fortawesome/free-solid-svg-icons/faSubtract"; +export { definition as faSubway } from "@fortawesome/free-solid-svg-icons/faSubway"; +export { definition as faSuitcase } from "@fortawesome/free-solid-svg-icons/faSuitcase"; +export { definition as faSuitcaseMedical } from "@fortawesome/free-solid-svg-icons/faSuitcaseMedical"; +export { definition as faSuitcaseRolling } from "@fortawesome/free-solid-svg-icons/faSuitcaseRolling"; +export { definition as faSun } from "@fortawesome/free-solid-svg-icons/faSun"; +export { definition as faSunPlantWilt } from "@fortawesome/free-solid-svg-icons/faSunPlantWilt"; +export { definition as faSuperscript } from "@fortawesome/free-solid-svg-icons/faSuperscript"; +export { definition as faSurprise } from "@fortawesome/free-solid-svg-icons/faSurprise"; +export { definition as faSwatchbook } from "@fortawesome/free-solid-svg-icons/faSwatchbook"; +export { definition as faSwimmer } from "@fortawesome/free-solid-svg-icons/faSwimmer"; +export { definition as faSwimmingPool } from "@fortawesome/free-solid-svg-icons/faSwimmingPool"; +export { definition as faSynagogue } from "@fortawesome/free-solid-svg-icons/faSynagogue"; +export { definition as faSync } from "@fortawesome/free-solid-svg-icons/faSync"; +export { definition as faSyncAlt } from "@fortawesome/free-solid-svg-icons/faSyncAlt"; +export { definition as faSyringe } from "@fortawesome/free-solid-svg-icons/faSyringe"; +export { definition as faT } from "@fortawesome/free-solid-svg-icons/faT"; +export { definition as faTShirt } from "@fortawesome/free-solid-svg-icons/faTShirt"; +export { definition as faTable } from "@fortawesome/free-solid-svg-icons/faTable"; +export { definition as faTableCells } from "@fortawesome/free-solid-svg-icons/faTableCells"; +export { definition as faTableCellsColumnLock } from "@fortawesome/free-solid-svg-icons/faTableCellsColumnLock"; +export { definition as faTableCellsLarge } from "@fortawesome/free-solid-svg-icons/faTableCellsLarge"; +export { definition as faTableCellsRowLock } from "@fortawesome/free-solid-svg-icons/faTableCellsRowLock"; +export { definition as faTableCellsRowUnlock } from "@fortawesome/free-solid-svg-icons/faTableCellsRowUnlock"; +export { definition as faTableColumns } from "@fortawesome/free-solid-svg-icons/faTableColumns"; +export { definition as faTableList } from "@fortawesome/free-solid-svg-icons/faTableList"; +export { definition as faTableTennis } from "@fortawesome/free-solid-svg-icons/faTableTennis"; +export { definition as faTableTennisPaddleBall } from "@fortawesome/free-solid-svg-icons/faTableTennisPaddleBall"; +export { definition as faTablet } from "@fortawesome/free-solid-svg-icons/faTablet"; +export { definition as faTabletAlt } from "@fortawesome/free-solid-svg-icons/faTabletAlt"; +export { definition as faTabletAndroid } from "@fortawesome/free-solid-svg-icons/faTabletAndroid"; +export { definition as faTabletButton } from "@fortawesome/free-solid-svg-icons/faTabletButton"; +export { definition as faTabletScreenButton } from "@fortawesome/free-solid-svg-icons/faTabletScreenButton"; +export { definition as faTablets } from "@fortawesome/free-solid-svg-icons/faTablets"; +export { definition as faTachographDigital } from "@fortawesome/free-solid-svg-icons/faTachographDigital"; +export { definition as faTachometer } from "@fortawesome/free-solid-svg-icons/faTachometer"; +export { definition as faTachometerAlt } from "@fortawesome/free-solid-svg-icons/faTachometerAlt"; +export { definition as faTachometerAltAverage } from "@fortawesome/free-solid-svg-icons/faTachometerAltAverage"; +export { definition as faTachometerAltFast } from "@fortawesome/free-solid-svg-icons/faTachometerAltFast"; +export { definition as faTachometerAverage } from "@fortawesome/free-solid-svg-icons/faTachometerAverage"; +export { definition as faTachometerFast } from "@fortawesome/free-solid-svg-icons/faTachometerFast"; +export { definition as faTag } from "@fortawesome/free-solid-svg-icons/faTag"; +export { definition as faTags } from "@fortawesome/free-solid-svg-icons/faTags"; +export { definition as faTanakh } from "@fortawesome/free-solid-svg-icons/faTanakh"; +export { definition as faTape } from "@fortawesome/free-solid-svg-icons/faTape"; +export { definition as faTarp } from "@fortawesome/free-solid-svg-icons/faTarp"; +export { definition as faTarpDroplet } from "@fortawesome/free-solid-svg-icons/faTarpDroplet"; +export { definition as faTasks } from "@fortawesome/free-solid-svg-icons/faTasks"; +export { definition as faTasksAlt } from "@fortawesome/free-solid-svg-icons/faTasksAlt"; +export { definition as faTaxi } from "@fortawesome/free-solid-svg-icons/faTaxi"; +export { definition as faTeeth } from "@fortawesome/free-solid-svg-icons/faTeeth"; +export { definition as faTeethOpen } from "@fortawesome/free-solid-svg-icons/faTeethOpen"; +export { definition as faTeletype } from "@fortawesome/free-solid-svg-icons/faTeletype"; +export { definition as faTelevision } from "@fortawesome/free-solid-svg-icons/faTelevision"; +export { definition as faTemperature0 } from "@fortawesome/free-solid-svg-icons/faTemperature0"; +export { definition as faTemperature1 } from "@fortawesome/free-solid-svg-icons/faTemperature1"; +export { definition as faTemperature2 } from "@fortawesome/free-solid-svg-icons/faTemperature2"; +export { definition as faTemperature3 } from "@fortawesome/free-solid-svg-icons/faTemperature3"; +export { definition as faTemperature4 } from "@fortawesome/free-solid-svg-icons/faTemperature4"; +export { definition as faTemperatureArrowDown } from "@fortawesome/free-solid-svg-icons/faTemperatureArrowDown"; +export { definition as faTemperatureArrowUp } from "@fortawesome/free-solid-svg-icons/faTemperatureArrowUp"; +export { definition as faTemperatureDown } from "@fortawesome/free-solid-svg-icons/faTemperatureDown"; +export { definition as faTemperatureEmpty } from "@fortawesome/free-solid-svg-icons/faTemperatureEmpty"; +export { definition as faTemperatureFull } from "@fortawesome/free-solid-svg-icons/faTemperatureFull"; +export { definition as faTemperatureHalf } from "@fortawesome/free-solid-svg-icons/faTemperatureHalf"; +export { definition as faTemperatureHigh } from "@fortawesome/free-solid-svg-icons/faTemperatureHigh"; +export { definition as faTemperatureLow } from "@fortawesome/free-solid-svg-icons/faTemperatureLow"; +export { definition as faTemperatureQuarter } from "@fortawesome/free-solid-svg-icons/faTemperatureQuarter"; +export { definition as faTemperatureThreeQuarters } from "@fortawesome/free-solid-svg-icons/faTemperatureThreeQuarters"; +export { definition as faTemperatureUp } from "@fortawesome/free-solid-svg-icons/faTemperatureUp"; +export { definition as faTenge } from "@fortawesome/free-solid-svg-icons/faTenge"; +export { definition as faTengeSign } from "@fortawesome/free-solid-svg-icons/faTengeSign"; +export { definition as faTent } from "@fortawesome/free-solid-svg-icons/faTent"; +export { definition as faTentArrowDownToLine } from "@fortawesome/free-solid-svg-icons/faTentArrowDownToLine"; +export { definition as faTentArrowLeftRight } from "@fortawesome/free-solid-svg-icons/faTentArrowLeftRight"; +export { definition as faTentArrowTurnLeft } from "@fortawesome/free-solid-svg-icons/faTentArrowTurnLeft"; +export { definition as faTentArrowsDown } from "@fortawesome/free-solid-svg-icons/faTentArrowsDown"; +export { definition as faTents } from "@fortawesome/free-solid-svg-icons/faTents"; +export { definition as faTerminal } from "@fortawesome/free-solid-svg-icons/faTerminal"; +export { definition as faTextHeight } from "@fortawesome/free-solid-svg-icons/faTextHeight"; +export { definition as faTextSlash } from "@fortawesome/free-solid-svg-icons/faTextSlash"; +export { definition as faTextWidth } from "@fortawesome/free-solid-svg-icons/faTextWidth"; +export { definition as faTh } from "@fortawesome/free-solid-svg-icons/faTh"; +export { definition as faThLarge } from "@fortawesome/free-solid-svg-icons/faThLarge"; +export { definition as faThList } from "@fortawesome/free-solid-svg-icons/faThList"; +export { definition as faTheaterMasks } from "@fortawesome/free-solid-svg-icons/faTheaterMasks"; +export { definition as faThermometer } from "@fortawesome/free-solid-svg-icons/faThermometer"; +export { definition as faThermometer0 } from "@fortawesome/free-solid-svg-icons/faThermometer0"; +export { definition as faThermometer1 } from "@fortawesome/free-solid-svg-icons/faThermometer1"; +export { definition as faThermometer2 } from "@fortawesome/free-solid-svg-icons/faThermometer2"; +export { definition as faThermometer3 } from "@fortawesome/free-solid-svg-icons/faThermometer3"; +export { definition as faThermometer4 } from "@fortawesome/free-solid-svg-icons/faThermometer4"; +export { definition as faThermometerEmpty } from "@fortawesome/free-solid-svg-icons/faThermometerEmpty"; +export { definition as faThermometerFull } from "@fortawesome/free-solid-svg-icons/faThermometerFull"; +export { definition as faThermometerHalf } from "@fortawesome/free-solid-svg-icons/faThermometerHalf"; +export { definition as faThermometerQuarter } from "@fortawesome/free-solid-svg-icons/faThermometerQuarter"; +export { definition as faThermometerThreeQuarters } from "@fortawesome/free-solid-svg-icons/faThermometerThreeQuarters"; +export { definition as faThumbsDown } from "@fortawesome/free-solid-svg-icons/faThumbsDown"; +export { definition as faThumbsUp } from "@fortawesome/free-solid-svg-icons/faThumbsUp"; +export { definition as faThumbtack } from "@fortawesome/free-solid-svg-icons/faThumbtack"; +export { definition as faThumbtackSlash } from "@fortawesome/free-solid-svg-icons/faThumbtackSlash"; +export { definition as faThunderstorm } from "@fortawesome/free-solid-svg-icons/faThunderstorm"; +export { definition as faTicket } from "@fortawesome/free-solid-svg-icons/faTicket"; +export { definition as faTicketAlt } from "@fortawesome/free-solid-svg-icons/faTicketAlt"; +export { definition as faTicketSimple } from "@fortawesome/free-solid-svg-icons/faTicketSimple"; +export { definition as faTimeline } from "@fortawesome/free-solid-svg-icons/faTimeline"; +export { definition as faTimes } from "@fortawesome/free-solid-svg-icons/faTimes"; +export { definition as faTimesCircle } from "@fortawesome/free-solid-svg-icons/faTimesCircle"; +export { definition as faTimesRectangle } from "@fortawesome/free-solid-svg-icons/faTimesRectangle"; +export { definition as faTimesSquare } from "@fortawesome/free-solid-svg-icons/faTimesSquare"; +export { definition as faTint } from "@fortawesome/free-solid-svg-icons/faTint"; +export { definition as faTintSlash } from "@fortawesome/free-solid-svg-icons/faTintSlash"; +export { definition as faTired } from "@fortawesome/free-solid-svg-icons/faTired"; +export { definition as faToggleOff } from "@fortawesome/free-solid-svg-icons/faToggleOff"; +export { definition as faToggleOn } from "@fortawesome/free-solid-svg-icons/faToggleOn"; +export { definition as faToilet } from "@fortawesome/free-solid-svg-icons/faToilet"; +export { definition as faToiletPaper } from "@fortawesome/free-solid-svg-icons/faToiletPaper"; +export { definition as faToiletPaperSlash } from "@fortawesome/free-solid-svg-icons/faToiletPaperSlash"; +export { definition as faToiletPortable } from "@fortawesome/free-solid-svg-icons/faToiletPortable"; +export { definition as faToiletsPortable } from "@fortawesome/free-solid-svg-icons/faToiletsPortable"; +export { definition as faToolbox } from "@fortawesome/free-solid-svg-icons/faToolbox"; +export { definition as faTools } from "@fortawesome/free-solid-svg-icons/faTools"; +export { definition as faTooth } from "@fortawesome/free-solid-svg-icons/faTooth"; +export { definition as faTorah } from "@fortawesome/free-solid-svg-icons/faTorah"; +export { definition as faToriiGate } from "@fortawesome/free-solid-svg-icons/faToriiGate"; +export { definition as faTornado } from "@fortawesome/free-solid-svg-icons/faTornado"; +export { definition as faTowerBroadcast } from "@fortawesome/free-solid-svg-icons/faTowerBroadcast"; +export { definition as faTowerCell } from "@fortawesome/free-solid-svg-icons/faTowerCell"; +export { definition as faTowerObservation } from "@fortawesome/free-solid-svg-icons/faTowerObservation"; +export { definition as faTractor } from "@fortawesome/free-solid-svg-icons/faTractor"; +export { definition as faTrademark } from "@fortawesome/free-solid-svg-icons/faTrademark"; +export { definition as faTrafficLight } from "@fortawesome/free-solid-svg-icons/faTrafficLight"; +export { definition as faTrailer } from "@fortawesome/free-solid-svg-icons/faTrailer"; +export { definition as faTrain } from "@fortawesome/free-solid-svg-icons/faTrain"; +export { definition as faTrainSubway } from "@fortawesome/free-solid-svg-icons/faTrainSubway"; +export { definition as faTrainTram } from "@fortawesome/free-solid-svg-icons/faTrainTram"; +export { definition as faTram } from "@fortawesome/free-solid-svg-icons/faTram"; +export { definition as faTransgender } from "@fortawesome/free-solid-svg-icons/faTransgender"; +export { definition as faTransgenderAlt } from "@fortawesome/free-solid-svg-icons/faTransgenderAlt"; +export { definition as faTrash } from "@fortawesome/free-solid-svg-icons/faTrash"; +export { definition as faTrashAlt } from "@fortawesome/free-solid-svg-icons/faTrashAlt"; +export { definition as faTrashArrowUp } from "@fortawesome/free-solid-svg-icons/faTrashArrowUp"; +export { definition as faTrashCan } from "@fortawesome/free-solid-svg-icons/faTrashCan"; +export { definition as faTrashCanArrowUp } from "@fortawesome/free-solid-svg-icons/faTrashCanArrowUp"; +export { definition as faTrashRestore } from "@fortawesome/free-solid-svg-icons/faTrashRestore"; +export { definition as faTrashRestoreAlt } from "@fortawesome/free-solid-svg-icons/faTrashRestoreAlt"; +export { definition as faTree } from "@fortawesome/free-solid-svg-icons/faTree"; +export { definition as faTreeCity } from "@fortawesome/free-solid-svg-icons/faTreeCity"; +export { definition as faTriangleCircleSquare } from "@fortawesome/free-solid-svg-icons/faTriangleCircleSquare"; +export { definition as faTriangleExclamation } from "@fortawesome/free-solid-svg-icons/faTriangleExclamation"; +export { definition as faTrophy } from "@fortawesome/free-solid-svg-icons/faTrophy"; +export { definition as faTrowel } from "@fortawesome/free-solid-svg-icons/faTrowel"; +export { definition as faTrowelBricks } from "@fortawesome/free-solid-svg-icons/faTrowelBricks"; +export { definition as faTruck } from "@fortawesome/free-solid-svg-icons/faTruck"; +export { definition as faTruckArrowRight } from "@fortawesome/free-solid-svg-icons/faTruckArrowRight"; +export { definition as faTruckDroplet } from "@fortawesome/free-solid-svg-icons/faTruckDroplet"; +export { definition as faTruckFast } from "@fortawesome/free-solid-svg-icons/faTruckFast"; +export { definition as faTruckField } from "@fortawesome/free-solid-svg-icons/faTruckField"; +export { definition as faTruckFieldUn } from "@fortawesome/free-solid-svg-icons/faTruckFieldUn"; +export { definition as faTruckFront } from "@fortawesome/free-solid-svg-icons/faTruckFront"; +export { definition as faTruckLoading } from "@fortawesome/free-solid-svg-icons/faTruckLoading"; +export { definition as faTruckMedical } from "@fortawesome/free-solid-svg-icons/faTruckMedical"; +export { definition as faTruckMonster } from "@fortawesome/free-solid-svg-icons/faTruckMonster"; +export { definition as faTruckMoving } from "@fortawesome/free-solid-svg-icons/faTruckMoving"; +export { definition as faTruckPickup } from "@fortawesome/free-solid-svg-icons/faTruckPickup"; +export { definition as faTruckPlane } from "@fortawesome/free-solid-svg-icons/faTruckPlane"; +export { definition as faTruckRampBox } from "@fortawesome/free-solid-svg-icons/faTruckRampBox"; +export { definition as faTry } from "@fortawesome/free-solid-svg-icons/faTry"; +export { definition as faTty } from "@fortawesome/free-solid-svg-icons/faTty"; +export { definition as faTurkishLira } from "@fortawesome/free-solid-svg-icons/faTurkishLira"; +export { definition as faTurkishLiraSign } from "@fortawesome/free-solid-svg-icons/faTurkishLiraSign"; +export { definition as faTurnDown } from "@fortawesome/free-solid-svg-icons/faTurnDown"; +export { definition as faTurnUp } from "@fortawesome/free-solid-svg-icons/faTurnUp"; +export { definition as faTv } from "@fortawesome/free-solid-svg-icons/faTv"; +export { definition as faTvAlt } from "@fortawesome/free-solid-svg-icons/faTvAlt"; +export { definition as faU } from "@fortawesome/free-solid-svg-icons/faU"; +export { definition as faUmbrella } from "@fortawesome/free-solid-svg-icons/faUmbrella"; +export { definition as faUmbrellaBeach } from "@fortawesome/free-solid-svg-icons/faUmbrellaBeach"; +export { definition as faUnderline } from "@fortawesome/free-solid-svg-icons/faUnderline"; +export { definition as faUndo } from "@fortawesome/free-solid-svg-icons/faUndo"; +export { definition as faUndoAlt } from "@fortawesome/free-solid-svg-icons/faUndoAlt"; +export { definition as faUniversalAccess } from "@fortawesome/free-solid-svg-icons/faUniversalAccess"; +export { definition as faUniversity } from "@fortawesome/free-solid-svg-icons/faUniversity"; +export { definition as faUnlink } from "@fortawesome/free-solid-svg-icons/faUnlink"; +export { definition as faUnlock } from "@fortawesome/free-solid-svg-icons/faUnlock"; +export { definition as faUnlockAlt } from "@fortawesome/free-solid-svg-icons/faUnlockAlt"; +export { definition as faUnlockKeyhole } from "@fortawesome/free-solid-svg-icons/faUnlockKeyhole"; +export { definition as faUnsorted } from "@fortawesome/free-solid-svg-icons/faUnsorted"; +export { definition as faUpDown } from "@fortawesome/free-solid-svg-icons/faUpDown"; +export { definition as faUpDownLeftRight } from "@fortawesome/free-solid-svg-icons/faUpDownLeftRight"; +export { definition as faUpLong } from "@fortawesome/free-solid-svg-icons/faUpLong"; +export { definition as faUpRightAndDownLeftFromCenter } from "@fortawesome/free-solid-svg-icons/faUpRightAndDownLeftFromCenter"; +export { definition as faUpRightFromSquare } from "@fortawesome/free-solid-svg-icons/faUpRightFromSquare"; +export { definition as faUpload } from "@fortawesome/free-solid-svg-icons/faUpload"; +export { definition as faUsd } from "@fortawesome/free-solid-svg-icons/faUsd"; +export { definition as faUser } from "@fortawesome/free-solid-svg-icons/faUser"; +export { definition as faUserAlt } from "@fortawesome/free-solid-svg-icons/faUserAlt"; +export { definition as faUserAltSlash } from "@fortawesome/free-solid-svg-icons/faUserAltSlash"; +export { definition as faUserAstronaut } from "@fortawesome/free-solid-svg-icons/faUserAstronaut"; +export { definition as faUserCheck } from "@fortawesome/free-solid-svg-icons/faUserCheck"; +export { definition as faUserCircle } from "@fortawesome/free-solid-svg-icons/faUserCircle"; +export { definition as faUserClock } from "@fortawesome/free-solid-svg-icons/faUserClock"; +export { definition as faUserCog } from "@fortawesome/free-solid-svg-icons/faUserCog"; +export { definition as faUserDoctor } from "@fortawesome/free-solid-svg-icons/faUserDoctor"; +export { definition as faUserEdit } from "@fortawesome/free-solid-svg-icons/faUserEdit"; +export { definition as faUserFriends } from "@fortawesome/free-solid-svg-icons/faUserFriends"; +export { definition as faUserGear } from "@fortawesome/free-solid-svg-icons/faUserGear"; +export { definition as faUserGraduate } from "@fortawesome/free-solid-svg-icons/faUserGraduate"; +export { definition as faUserGroup } from "@fortawesome/free-solid-svg-icons/faUserGroup"; +export { definition as faUserInjured } from "@fortawesome/free-solid-svg-icons/faUserInjured"; +export { definition as faUserLarge } from "@fortawesome/free-solid-svg-icons/faUserLarge"; +export { definition as faUserLargeSlash } from "@fortawesome/free-solid-svg-icons/faUserLargeSlash"; +export { definition as faUserLock } from "@fortawesome/free-solid-svg-icons/faUserLock"; +export { definition as faUserMd } from "@fortawesome/free-solid-svg-icons/faUserMd"; +export { definition as faUserMinus } from "@fortawesome/free-solid-svg-icons/faUserMinus"; +export { definition as faUserNinja } from "@fortawesome/free-solid-svg-icons/faUserNinja"; +export { definition as faUserNurse } from "@fortawesome/free-solid-svg-icons/faUserNurse"; +export { definition as faUserPen } from "@fortawesome/free-solid-svg-icons/faUserPen"; +export { definition as faUserPlus } from "@fortawesome/free-solid-svg-icons/faUserPlus"; +export { definition as faUserSecret } from "@fortawesome/free-solid-svg-icons/faUserSecret"; +export { definition as faUserShield } from "@fortawesome/free-solid-svg-icons/faUserShield"; +export { definition as faUserSlash } from "@fortawesome/free-solid-svg-icons/faUserSlash"; +export { definition as faUserTag } from "@fortawesome/free-solid-svg-icons/faUserTag"; +export { definition as faUserTie } from "@fortawesome/free-solid-svg-icons/faUserTie"; +export { definition as faUserTimes } from "@fortawesome/free-solid-svg-icons/faUserTimes"; +export { definition as faUserXmark } from "@fortawesome/free-solid-svg-icons/faUserXmark"; +export { definition as faUsers } from "@fortawesome/free-solid-svg-icons/faUsers"; +export { definition as faUsersBetweenLines } from "@fortawesome/free-solid-svg-icons/faUsersBetweenLines"; +export { definition as faUsersCog } from "@fortawesome/free-solid-svg-icons/faUsersCog"; +export { definition as faUsersGear } from "@fortawesome/free-solid-svg-icons/faUsersGear"; +export { definition as faUsersLine } from "@fortawesome/free-solid-svg-icons/faUsersLine"; +export { definition as faUsersRays } from "@fortawesome/free-solid-svg-icons/faUsersRays"; +export { definition as faUsersRectangle } from "@fortawesome/free-solid-svg-icons/faUsersRectangle"; +export { definition as faUsersSlash } from "@fortawesome/free-solid-svg-icons/faUsersSlash"; +export { definition as faUsersViewfinder } from "@fortawesome/free-solid-svg-icons/faUsersViewfinder"; +export { definition as faUtensilSpoon } from "@fortawesome/free-solid-svg-icons/faUtensilSpoon"; +export { definition as faUtensils } from "@fortawesome/free-solid-svg-icons/faUtensils"; +export { definition as faV } from "@fortawesome/free-solid-svg-icons/faV"; +export { definition as faVanShuttle } from "@fortawesome/free-solid-svg-icons/faVanShuttle"; +export { definition as faVault } from "@fortawesome/free-solid-svg-icons/faVault"; +export { definition as faVcard } from "@fortawesome/free-solid-svg-icons/faVcard"; +export { definition as faVectorSquare } from "@fortawesome/free-solid-svg-icons/faVectorSquare"; +export { definition as faVenus } from "@fortawesome/free-solid-svg-icons/faVenus"; +export { definition as faVenusDouble } from "@fortawesome/free-solid-svg-icons/faVenusDouble"; +export { definition as faVenusMars } from "@fortawesome/free-solid-svg-icons/faVenusMars"; +export { definition as faVest } from "@fortawesome/free-solid-svg-icons/faVest"; +export { definition as faVestPatches } from "@fortawesome/free-solid-svg-icons/faVestPatches"; +export { definition as faVial } from "@fortawesome/free-solid-svg-icons/faVial"; +export { definition as faVialCircleCheck } from "@fortawesome/free-solid-svg-icons/faVialCircleCheck"; +export { definition as faVialVirus } from "@fortawesome/free-solid-svg-icons/faVialVirus"; +export { definition as faVials } from "@fortawesome/free-solid-svg-icons/faVials"; +export { definition as faVideo } from "@fortawesome/free-solid-svg-icons/faVideo"; +export { definition as faVideoCamera } from "@fortawesome/free-solid-svg-icons/faVideoCamera"; +export { definition as faVideoSlash } from "@fortawesome/free-solid-svg-icons/faVideoSlash"; +export { definition as faVihara } from "@fortawesome/free-solid-svg-icons/faVihara"; +export { definition as faVirus } from "@fortawesome/free-solid-svg-icons/faVirus"; +export { definition as faVirusCovid } from "@fortawesome/free-solid-svg-icons/faVirusCovid"; +export { definition as faVirusCovidSlash } from "@fortawesome/free-solid-svg-icons/faVirusCovidSlash"; +export { definition as faVirusSlash } from "@fortawesome/free-solid-svg-icons/faVirusSlash"; +export { definition as faViruses } from "@fortawesome/free-solid-svg-icons/faViruses"; +export { definition as faVoicemail } from "@fortawesome/free-solid-svg-icons/faVoicemail"; +export { definition as faVolcano } from "@fortawesome/free-solid-svg-icons/faVolcano"; +export { definition as faVolleyball } from "@fortawesome/free-solid-svg-icons/faVolleyball"; +export { definition as faVolleyballBall } from "@fortawesome/free-solid-svg-icons/faVolleyballBall"; +export { definition as faVolumeControlPhone } from "@fortawesome/free-solid-svg-icons/faVolumeControlPhone"; +export { definition as faVolumeDown } from "@fortawesome/free-solid-svg-icons/faVolumeDown"; +export { definition as faVolumeHigh } from "@fortawesome/free-solid-svg-icons/faVolumeHigh"; +export { definition as faVolumeLow } from "@fortawesome/free-solid-svg-icons/faVolumeLow"; +export { definition as faVolumeMute } from "@fortawesome/free-solid-svg-icons/faVolumeMute"; +export { definition as faVolumeOff } from "@fortawesome/free-solid-svg-icons/faVolumeOff"; +export { definition as faVolumeTimes } from "@fortawesome/free-solid-svg-icons/faVolumeTimes"; +export { definition as faVolumeUp } from "@fortawesome/free-solid-svg-icons/faVolumeUp"; +export { definition as faVolumeXmark } from "@fortawesome/free-solid-svg-icons/faVolumeXmark"; +export { definition as faVoteYea } from "@fortawesome/free-solid-svg-icons/faVoteYea"; +export { definition as faVrCardboard } from "@fortawesome/free-solid-svg-icons/faVrCardboard"; +export { definition as faW } from "@fortawesome/free-solid-svg-icons/faW"; +export { definition as faWalkieTalkie } from "@fortawesome/free-solid-svg-icons/faWalkieTalkie"; +export { definition as faWalking } from "@fortawesome/free-solid-svg-icons/faWalking"; +export { definition as faWallet } from "@fortawesome/free-solid-svg-icons/faWallet"; +export { definition as faWandMagic } from "@fortawesome/free-solid-svg-icons/faWandMagic"; +export { definition as faWandMagicSparkles } from "@fortawesome/free-solid-svg-icons/faWandMagicSparkles"; +export { definition as faWandSparkles } from "@fortawesome/free-solid-svg-icons/faWandSparkles"; +export { definition as faWarehouse } from "@fortawesome/free-solid-svg-icons/faWarehouse"; +export { definition as faWarning } from "@fortawesome/free-solid-svg-icons/faWarning"; +export { definition as faWater } from "@fortawesome/free-solid-svg-icons/faWater"; +export { definition as faWaterLadder } from "@fortawesome/free-solid-svg-icons/faWaterLadder"; +export { definition as faWaveSquare } from "@fortawesome/free-solid-svg-icons/faWaveSquare"; +export { definition as faWebAwesome } from "@fortawesome/free-solid-svg-icons/faWebAwesome"; +export { definition as faWeight } from "@fortawesome/free-solid-svg-icons/faWeight"; +export { definition as faWeightHanging } from "@fortawesome/free-solid-svg-icons/faWeightHanging"; +export { definition as faWeightScale } from "@fortawesome/free-solid-svg-icons/faWeightScale"; +export { definition as faWheatAlt } from "@fortawesome/free-solid-svg-icons/faWheatAlt"; +export { definition as faWheatAwn } from "@fortawesome/free-solid-svg-icons/faWheatAwn"; +export { definition as faWheatAwnCircleExclamation } from "@fortawesome/free-solid-svg-icons/faWheatAwnCircleExclamation"; +export { definition as faWheelchair } from "@fortawesome/free-solid-svg-icons/faWheelchair"; +export { definition as faWheelchairAlt } from "@fortawesome/free-solid-svg-icons/faWheelchairAlt"; +export { definition as faWheelchairMove } from "@fortawesome/free-solid-svg-icons/faWheelchairMove"; +export { definition as faWhiskeyGlass } from "@fortawesome/free-solid-svg-icons/faWhiskeyGlass"; +export { definition as faWifi } from "@fortawesome/free-solid-svg-icons/faWifi"; +export { definition as faWifi3 } from "@fortawesome/free-solid-svg-icons/faWifi3"; +export { definition as faWifiStrong } from "@fortawesome/free-solid-svg-icons/faWifiStrong"; +export { definition as faWind } from "@fortawesome/free-solid-svg-icons/faWind"; +export { definition as faWindowClose } from "@fortawesome/free-solid-svg-icons/faWindowClose"; +export { definition as faWindowMaximize } from "@fortawesome/free-solid-svg-icons/faWindowMaximize"; +export { definition as faWindowMinimize } from "@fortawesome/free-solid-svg-icons/faWindowMinimize"; +export { definition as faWindowRestore } from "@fortawesome/free-solid-svg-icons/faWindowRestore"; +export { definition as faWineBottle } from "@fortawesome/free-solid-svg-icons/faWineBottle"; +export { definition as faWineGlass } from "@fortawesome/free-solid-svg-icons/faWineGlass"; +export { definition as faWineGlassAlt } from "@fortawesome/free-solid-svg-icons/faWineGlassAlt"; +export { definition as faWineGlassEmpty } from "@fortawesome/free-solid-svg-icons/faWineGlassEmpty"; +export { definition as faWon } from "@fortawesome/free-solid-svg-icons/faWon"; +export { definition as faWonSign } from "@fortawesome/free-solid-svg-icons/faWonSign"; +export { definition as faWorm } from "@fortawesome/free-solid-svg-icons/faWorm"; +export { definition as faWrench } from "@fortawesome/free-solid-svg-icons/faWrench"; +export { definition as faX } from "@fortawesome/free-solid-svg-icons/faX"; +export { definition as faXRay } from "@fortawesome/free-solid-svg-icons/faXRay"; +export { definition as faXmark } from "@fortawesome/free-solid-svg-icons/faXmark"; +export { definition as faXmarkCircle } from "@fortawesome/free-solid-svg-icons/faXmarkCircle"; +export { definition as faXmarkSquare } from "@fortawesome/free-solid-svg-icons/faXmarkSquare"; +export { definition as faXmarksLines } from "@fortawesome/free-solid-svg-icons/faXmarksLines"; +export { definition as faY } from "@fortawesome/free-solid-svg-icons/faY"; +export { definition as faYen } from "@fortawesome/free-solid-svg-icons/faYen"; +export { definition as faYenSign } from "@fortawesome/free-solid-svg-icons/faYenSign"; +export { definition as faYinYang } from "@fortawesome/free-solid-svg-icons/faYinYang"; +export { definition as faZ } from "@fortawesome/free-solid-svg-icons/faZ"; +export { definition as faZap } from "@fortawesome/free-solid-svg-icons/faZap"; +export { definition as fa42Group } from "@fortawesome/free-brands-svg-icons/fa42Group"; +export { definition as fa500px } from "@fortawesome/free-brands-svg-icons/fa500px"; +export { definition as faAccessibleIcon } from "@fortawesome/free-brands-svg-icons/faAccessibleIcon"; +export { definition as faAccusoft } from "@fortawesome/free-brands-svg-icons/faAccusoft"; +export { definition as faAdn } from "@fortawesome/free-brands-svg-icons/faAdn"; +export { definition as faAdversal } from "@fortawesome/free-brands-svg-icons/faAdversal"; +export { definition as faAffiliatetheme } from "@fortawesome/free-brands-svg-icons/faAffiliatetheme"; +export { definition as faAirbnb } from "@fortawesome/free-brands-svg-icons/faAirbnb"; +export { definition as faAlgolia } from "@fortawesome/free-brands-svg-icons/faAlgolia"; +export { definition as faAlipay } from "@fortawesome/free-brands-svg-icons/faAlipay"; +export { definition as faAmazon } from "@fortawesome/free-brands-svg-icons/faAmazon"; +export { definition as faAmazonPay } from "@fortawesome/free-brands-svg-icons/faAmazonPay"; +export { definition as faAmilia } from "@fortawesome/free-brands-svg-icons/faAmilia"; +export { definition as faAndroid } from "@fortawesome/free-brands-svg-icons/faAndroid"; +export { definition as faAngellist } from "@fortawesome/free-brands-svg-icons/faAngellist"; +export { definition as faAngrycreative } from "@fortawesome/free-brands-svg-icons/faAngrycreative"; +export { definition as faAngular } from "@fortawesome/free-brands-svg-icons/faAngular"; +export { definition as faAppStore } from "@fortawesome/free-brands-svg-icons/faAppStore"; +export { definition as faAppStoreIos } from "@fortawesome/free-brands-svg-icons/faAppStoreIos"; +export { definition as faApper } from "@fortawesome/free-brands-svg-icons/faApper"; +export { definition as faApple } from "@fortawesome/free-brands-svg-icons/faApple"; +export { definition as faApplePay } from "@fortawesome/free-brands-svg-icons/faApplePay"; +export { definition as faArtstation } from "@fortawesome/free-brands-svg-icons/faArtstation"; +export { definition as faAsymmetrik } from "@fortawesome/free-brands-svg-icons/faAsymmetrik"; +export { definition as faAtlassian } from "@fortawesome/free-brands-svg-icons/faAtlassian"; +export { definition as faAudible } from "@fortawesome/free-brands-svg-icons/faAudible"; +export { definition as faAutoprefixer } from "@fortawesome/free-brands-svg-icons/faAutoprefixer"; +export { definition as faAvianex } from "@fortawesome/free-brands-svg-icons/faAvianex"; +export { definition as faAviato } from "@fortawesome/free-brands-svg-icons/faAviato"; +export { definition as faAws } from "@fortawesome/free-brands-svg-icons/faAws"; +export { definition as faBandcamp } from "@fortawesome/free-brands-svg-icons/faBandcamp"; +export { definition as faBattleNet } from "@fortawesome/free-brands-svg-icons/faBattleNet"; +export { definition as faBehance } from "@fortawesome/free-brands-svg-icons/faBehance"; +export { definition as faBehanceSquare } from "@fortawesome/free-brands-svg-icons/faBehanceSquare"; +export { definition as faBilibili } from "@fortawesome/free-brands-svg-icons/faBilibili"; +export { definition as faBimobject } from "@fortawesome/free-brands-svg-icons/faBimobject"; +export { definition as faBitbucket } from "@fortawesome/free-brands-svg-icons/faBitbucket"; +export { definition as faBitcoin } from "@fortawesome/free-brands-svg-icons/faBitcoin"; +export { definition as faBity } from "@fortawesome/free-brands-svg-icons/faBity"; +export { definition as faBlackTie } from "@fortawesome/free-brands-svg-icons/faBlackTie"; +export { definition as faBlackberry } from "@fortawesome/free-brands-svg-icons/faBlackberry"; +export { definition as faBlogger } from "@fortawesome/free-brands-svg-icons/faBlogger"; +export { definition as faBloggerB } from "@fortawesome/free-brands-svg-icons/faBloggerB"; +export { definition as faBluesky } from "@fortawesome/free-brands-svg-icons/faBluesky"; +export { definition as faBluetooth } from "@fortawesome/free-brands-svg-icons/faBluetooth"; +export { definition as faBluetoothB } from "@fortawesome/free-brands-svg-icons/faBluetoothB"; +export { definition as faBootstrap } from "@fortawesome/free-brands-svg-icons/faBootstrap"; +export { definition as faBots } from "@fortawesome/free-brands-svg-icons/faBots"; +export { definition as faBrave } from "@fortawesome/free-brands-svg-icons/faBrave"; +export { definition as faBraveReverse } from "@fortawesome/free-brands-svg-icons/faBraveReverse"; +export { definition as faBtc } from "@fortawesome/free-brands-svg-icons/faBtc"; +export { definition as faBuffer } from "@fortawesome/free-brands-svg-icons/faBuffer"; +export { definition as faBuromobelexperte } from "@fortawesome/free-brands-svg-icons/faBuromobelexperte"; +export { definition as faBuyNLarge } from "@fortawesome/free-brands-svg-icons/faBuyNLarge"; +export { definition as faBuysellads } from "@fortawesome/free-brands-svg-icons/faBuysellads"; +export { definition as faCanadianMapleLeaf } from "@fortawesome/free-brands-svg-icons/faCanadianMapleLeaf"; +export { definition as faCcAmazonPay } from "@fortawesome/free-brands-svg-icons/faCcAmazonPay"; +export { definition as faCcAmex } from "@fortawesome/free-brands-svg-icons/faCcAmex"; +export { definition as faCcApplePay } from "@fortawesome/free-brands-svg-icons/faCcApplePay"; +export { definition as faCcDinersClub } from "@fortawesome/free-brands-svg-icons/faCcDinersClub"; +export { definition as faCcDiscover } from "@fortawesome/free-brands-svg-icons/faCcDiscover"; +export { definition as faCcJcb } from "@fortawesome/free-brands-svg-icons/faCcJcb"; +export { definition as faCcMastercard } from "@fortawesome/free-brands-svg-icons/faCcMastercard"; +export { definition as faCcPaypal } from "@fortawesome/free-brands-svg-icons/faCcPaypal"; +export { definition as faCcStripe } from "@fortawesome/free-brands-svg-icons/faCcStripe"; +export { definition as faCcVisa } from "@fortawesome/free-brands-svg-icons/faCcVisa"; +export { definition as faCentercode } from "@fortawesome/free-brands-svg-icons/faCentercode"; +export { definition as faCentos } from "@fortawesome/free-brands-svg-icons/faCentos"; +export { definition as faChrome } from "@fortawesome/free-brands-svg-icons/faChrome"; +export { definition as faChromecast } from "@fortawesome/free-brands-svg-icons/faChromecast"; +export { definition as faCloudflare } from "@fortawesome/free-brands-svg-icons/faCloudflare"; +export { definition as faCloudscale } from "@fortawesome/free-brands-svg-icons/faCloudscale"; +export { definition as faCloudsmith } from "@fortawesome/free-brands-svg-icons/faCloudsmith"; +export { definition as faCloudversify } from "@fortawesome/free-brands-svg-icons/faCloudversify"; +export { definition as faCmplid } from "@fortawesome/free-brands-svg-icons/faCmplid"; +export { definition as faCodepen } from "@fortawesome/free-brands-svg-icons/faCodepen"; +export { definition as faCodiepie } from "@fortawesome/free-brands-svg-icons/faCodiepie"; +export { definition as faConfluence } from "@fortawesome/free-brands-svg-icons/faConfluence"; +export { definition as faConnectdevelop } from "@fortawesome/free-brands-svg-icons/faConnectdevelop"; +export { definition as faContao } from "@fortawesome/free-brands-svg-icons/faContao"; +export { definition as faCottonBureau } from "@fortawesome/free-brands-svg-icons/faCottonBureau"; +export { definition as faCpanel } from "@fortawesome/free-brands-svg-icons/faCpanel"; +export { definition as faCreativeCommons } from "@fortawesome/free-brands-svg-icons/faCreativeCommons"; +export { definition as faCreativeCommonsBy } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsBy"; +export { definition as faCreativeCommonsNc } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsNc"; +export { definition as faCreativeCommonsNcEu } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsNcEu"; +export { definition as faCreativeCommonsNcJp } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsNcJp"; +export { definition as faCreativeCommonsNd } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsNd"; +export { definition as faCreativeCommonsPd } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsPd"; +export { definition as faCreativeCommonsPdAlt } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsPdAlt"; +export { definition as faCreativeCommonsRemix } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsRemix"; +export { definition as faCreativeCommonsSa } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsSa"; +export { definition as faCreativeCommonsSampling } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsSampling"; +export { definition as faCreativeCommonsSamplingPlus } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsSamplingPlus"; +export { definition as faCreativeCommonsShare } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsShare"; +export { definition as faCreativeCommonsZero } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsZero"; +export { definition as faCriticalRole } from "@fortawesome/free-brands-svg-icons/faCriticalRole"; +export { definition as faCss } from "@fortawesome/free-brands-svg-icons/faCss"; +export { definition as faCss3 } from "@fortawesome/free-brands-svg-icons/faCss3"; +export { definition as faCss3Alt } from "@fortawesome/free-brands-svg-icons/faCss3Alt"; +export { definition as faCuttlefish } from "@fortawesome/free-brands-svg-icons/faCuttlefish"; +export { definition as faDAndD } from "@fortawesome/free-brands-svg-icons/faDAndD"; +export { definition as faDAndDBeyond } from "@fortawesome/free-brands-svg-icons/faDAndDBeyond"; +export { definition as faDailymotion } from "@fortawesome/free-brands-svg-icons/faDailymotion"; +export { definition as faDartLang } from "@fortawesome/free-brands-svg-icons/faDartLang"; +export { definition as faDashcube } from "@fortawesome/free-brands-svg-icons/faDashcube"; +export { definition as faDebian } from "@fortawesome/free-brands-svg-icons/faDebian"; +export { definition as faDeezer } from "@fortawesome/free-brands-svg-icons/faDeezer"; +export { definition as faDelicious } from "@fortawesome/free-brands-svg-icons/faDelicious"; +export { definition as faDeploydog } from "@fortawesome/free-brands-svg-icons/faDeploydog"; +export { definition as faDeskpro } from "@fortawesome/free-brands-svg-icons/faDeskpro"; +export { definition as faDev } from "@fortawesome/free-brands-svg-icons/faDev"; +export { definition as faDeviantart } from "@fortawesome/free-brands-svg-icons/faDeviantart"; +export { definition as faDhl } from "@fortawesome/free-brands-svg-icons/faDhl"; +export { definition as faDiaspora } from "@fortawesome/free-brands-svg-icons/faDiaspora"; +export { definition as faDigg } from "@fortawesome/free-brands-svg-icons/faDigg"; +export { definition as faDigitalOcean } from "@fortawesome/free-brands-svg-icons/faDigitalOcean"; +export { definition as faDiscord } from "@fortawesome/free-brands-svg-icons/faDiscord"; +export { definition as faDiscourse } from "@fortawesome/free-brands-svg-icons/faDiscourse"; +export { definition as faDochub } from "@fortawesome/free-brands-svg-icons/faDochub"; +export { definition as faDocker } from "@fortawesome/free-brands-svg-icons/faDocker"; +export { definition as faDraft2digital } from "@fortawesome/free-brands-svg-icons/faDraft2digital"; +export { definition as faDribbble } from "@fortawesome/free-brands-svg-icons/faDribbble"; +export { definition as faDribbbleSquare } from "@fortawesome/free-brands-svg-icons/faDribbbleSquare"; +export { definition as faDropbox } from "@fortawesome/free-brands-svg-icons/faDropbox"; +export { definition as faDrupal } from "@fortawesome/free-brands-svg-icons/faDrupal"; +export { definition as faDyalog } from "@fortawesome/free-brands-svg-icons/faDyalog"; +export { definition as faEarlybirds } from "@fortawesome/free-brands-svg-icons/faEarlybirds"; +export { definition as faEbay } from "@fortawesome/free-brands-svg-icons/faEbay"; +export { definition as faEdge } from "@fortawesome/free-brands-svg-icons/faEdge"; +export { definition as faEdgeLegacy } from "@fortawesome/free-brands-svg-icons/faEdgeLegacy"; +export { definition as faElementor } from "@fortawesome/free-brands-svg-icons/faElementor"; +export { definition as faEllo } from "@fortawesome/free-brands-svg-icons/faEllo"; +export { definition as faEmber } from "@fortawesome/free-brands-svg-icons/faEmber"; +export { definition as faEmpire } from "@fortawesome/free-brands-svg-icons/faEmpire"; +export { definition as faEnvira } from "@fortawesome/free-brands-svg-icons/faEnvira"; +export { definition as faErlang } from "@fortawesome/free-brands-svg-icons/faErlang"; +export { definition as faEthereum } from "@fortawesome/free-brands-svg-icons/faEthereum"; +export { definition as faEtsy } from "@fortawesome/free-brands-svg-icons/faEtsy"; +export { definition as faEvernote } from "@fortawesome/free-brands-svg-icons/faEvernote"; +export { definition as faExpeditedssl } from "@fortawesome/free-brands-svg-icons/faExpeditedssl"; +export { definition as faFacebook } from "@fortawesome/free-brands-svg-icons/faFacebook"; +export { definition as faFacebookF } from "@fortawesome/free-brands-svg-icons/faFacebookF"; +export { definition as faFacebookMessenger } from "@fortawesome/free-brands-svg-icons/faFacebookMessenger"; +export { definition as faFacebookSquare } from "@fortawesome/free-brands-svg-icons/faFacebookSquare"; +export { definition as faFantasyFlightGames } from "@fortawesome/free-brands-svg-icons/faFantasyFlightGames"; +export { definition as faFedex } from "@fortawesome/free-brands-svg-icons/faFedex"; +export { definition as faFedora } from "@fortawesome/free-brands-svg-icons/faFedora"; +export { definition as faFigma } from "@fortawesome/free-brands-svg-icons/faFigma"; +export { definition as faFilesPinwheel } from "@fortawesome/free-brands-svg-icons/faFilesPinwheel"; +export { definition as faFirefox } from "@fortawesome/free-brands-svg-icons/faFirefox"; +export { definition as faFirefoxBrowser } from "@fortawesome/free-brands-svg-icons/faFirefoxBrowser"; +export { definition as faFirstOrder } from "@fortawesome/free-brands-svg-icons/faFirstOrder"; +export { definition as faFirstOrderAlt } from "@fortawesome/free-brands-svg-icons/faFirstOrderAlt"; +export { definition as faFirstdraft } from "@fortawesome/free-brands-svg-icons/faFirstdraft"; +export { definition as faFlickr } from "@fortawesome/free-brands-svg-icons/faFlickr"; +export { definition as faFlipboard } from "@fortawesome/free-brands-svg-icons/faFlipboard"; +export { definition as faFlutter } from "@fortawesome/free-brands-svg-icons/faFlutter"; +export { definition as faFly } from "@fortawesome/free-brands-svg-icons/faFly"; +export { definition as faFontAwesomeAlt } from "@fortawesome/free-brands-svg-icons/faFontAwesomeAlt"; +export { definition as faFonticons } from "@fortawesome/free-brands-svg-icons/faFonticons"; +export { definition as faFonticonsFi } from "@fortawesome/free-brands-svg-icons/faFonticonsFi"; +export { definition as faFortAwesome } from "@fortawesome/free-brands-svg-icons/faFortAwesome"; +export { definition as faFortAwesomeAlt } from "@fortawesome/free-brands-svg-icons/faFortAwesomeAlt"; +export { definition as faForumbee } from "@fortawesome/free-brands-svg-icons/faForumbee"; +export { definition as faFoursquare } from "@fortawesome/free-brands-svg-icons/faFoursquare"; +export { definition as faFreeCodeCamp } from "@fortawesome/free-brands-svg-icons/faFreeCodeCamp"; +export { definition as faFreebsd } from "@fortawesome/free-brands-svg-icons/faFreebsd"; +export { definition as faFulcrum } from "@fortawesome/free-brands-svg-icons/faFulcrum"; +export { definition as faGalacticRepublic } from "@fortawesome/free-brands-svg-icons/faGalacticRepublic"; +export { definition as faGalacticSenate } from "@fortawesome/free-brands-svg-icons/faGalacticSenate"; +export { definition as faGetPocket } from "@fortawesome/free-brands-svg-icons/faGetPocket"; +export { definition as faGg } from "@fortawesome/free-brands-svg-icons/faGg"; +export { definition as faGgCircle } from "@fortawesome/free-brands-svg-icons/faGgCircle"; +export { definition as faGit } from "@fortawesome/free-brands-svg-icons/faGit"; +export { definition as faGitAlt } from "@fortawesome/free-brands-svg-icons/faGitAlt"; +export { definition as faGitSquare } from "@fortawesome/free-brands-svg-icons/faGitSquare"; +export { definition as faGithub } from "@fortawesome/free-brands-svg-icons/faGithub"; +export { definition as faGithubAlt } from "@fortawesome/free-brands-svg-icons/faGithubAlt"; +export { definition as faGithubSquare } from "@fortawesome/free-brands-svg-icons/faGithubSquare"; +export { definition as faGitkraken } from "@fortawesome/free-brands-svg-icons/faGitkraken"; +export { definition as faGitlab } from "@fortawesome/free-brands-svg-icons/faGitlab"; +export { definition as faGitlabSquare } from "@fortawesome/free-brands-svg-icons/faGitlabSquare"; +export { definition as faGitter } from "@fortawesome/free-brands-svg-icons/faGitter"; +export { definition as faGlide } from "@fortawesome/free-brands-svg-icons/faGlide"; +export { definition as faGlideG } from "@fortawesome/free-brands-svg-icons/faGlideG"; +export { definition as faGofore } from "@fortawesome/free-brands-svg-icons/faGofore"; +export { definition as faGolang } from "@fortawesome/free-brands-svg-icons/faGolang"; +export { definition as faGoodreads } from "@fortawesome/free-brands-svg-icons/faGoodreads"; +export { definition as faGoodreadsG } from "@fortawesome/free-brands-svg-icons/faGoodreadsG"; +export { definition as faGoogle } from "@fortawesome/free-brands-svg-icons/faGoogle"; +export { definition as faGoogleDrive } from "@fortawesome/free-brands-svg-icons/faGoogleDrive"; +export { definition as faGooglePay } from "@fortawesome/free-brands-svg-icons/faGooglePay"; +export { definition as faGooglePlay } from "@fortawesome/free-brands-svg-icons/faGooglePlay"; +export { definition as faGooglePlus } from "@fortawesome/free-brands-svg-icons/faGooglePlus"; +export { definition as faGooglePlusG } from "@fortawesome/free-brands-svg-icons/faGooglePlusG"; +export { definition as faGooglePlusSquare } from "@fortawesome/free-brands-svg-icons/faGooglePlusSquare"; +export { definition as faGoogleScholar } from "@fortawesome/free-brands-svg-icons/faGoogleScholar"; +export { definition as faGoogleWallet } from "@fortawesome/free-brands-svg-icons/faGoogleWallet"; +export { definition as faGratipay } from "@fortawesome/free-brands-svg-icons/faGratipay"; +export { definition as faGrav } from "@fortawesome/free-brands-svg-icons/faGrav"; +export { definition as faGripfire } from "@fortawesome/free-brands-svg-icons/faGripfire"; +export { definition as faGrunt } from "@fortawesome/free-brands-svg-icons/faGrunt"; +export { definition as faGuilded } from "@fortawesome/free-brands-svg-icons/faGuilded"; +export { definition as faGulp } from "@fortawesome/free-brands-svg-icons/faGulp"; +export { definition as faHackerNews } from "@fortawesome/free-brands-svg-icons/faHackerNews"; +export { definition as faHackerNewsSquare } from "@fortawesome/free-brands-svg-icons/faHackerNewsSquare"; +export { definition as faHackerrank } from "@fortawesome/free-brands-svg-icons/faHackerrank"; +export { definition as faHashnode } from "@fortawesome/free-brands-svg-icons/faHashnode"; +export { definition as faHips } from "@fortawesome/free-brands-svg-icons/faHips"; +export { definition as faHireAHelper } from "@fortawesome/free-brands-svg-icons/faHireAHelper"; +export { definition as faHive } from "@fortawesome/free-brands-svg-icons/faHive"; +export { definition as faHooli } from "@fortawesome/free-brands-svg-icons/faHooli"; +export { definition as faHornbill } from "@fortawesome/free-brands-svg-icons/faHornbill"; +export { definition as faHotjar } from "@fortawesome/free-brands-svg-icons/faHotjar"; +export { definition as faHouzz } from "@fortawesome/free-brands-svg-icons/faHouzz"; +export { definition as faHtml5 } from "@fortawesome/free-brands-svg-icons/faHtml5"; +export { definition as faHubspot } from "@fortawesome/free-brands-svg-icons/faHubspot"; +export { definition as faIdeal } from "@fortawesome/free-brands-svg-icons/faIdeal"; +export { definition as faImdb } from "@fortawesome/free-brands-svg-icons/faImdb"; +export { definition as faInnosoft } from "@fortawesome/free-brands-svg-icons/faInnosoft"; +export { definition as faInstagram } from "@fortawesome/free-brands-svg-icons/faInstagram"; +export { definition as faInstagramSquare } from "@fortawesome/free-brands-svg-icons/faInstagramSquare"; +export { definition as faInstalod } from "@fortawesome/free-brands-svg-icons/faInstalod"; +export { definition as faIntercom } from "@fortawesome/free-brands-svg-icons/faIntercom"; +export { definition as faInternetExplorer } from "@fortawesome/free-brands-svg-icons/faInternetExplorer"; +export { definition as faInvision } from "@fortawesome/free-brands-svg-icons/faInvision"; +export { definition as faIoxhost } from "@fortawesome/free-brands-svg-icons/faIoxhost"; +export { definition as faItchIo } from "@fortawesome/free-brands-svg-icons/faItchIo"; +export { definition as faItunes } from "@fortawesome/free-brands-svg-icons/faItunes"; +export { definition as faItunesNote } from "@fortawesome/free-brands-svg-icons/faItunesNote"; +export { definition as faJava } from "@fortawesome/free-brands-svg-icons/faJava"; +export { definition as faJediOrder } from "@fortawesome/free-brands-svg-icons/faJediOrder"; +export { definition as faJenkins } from "@fortawesome/free-brands-svg-icons/faJenkins"; +export { definition as faJira } from "@fortawesome/free-brands-svg-icons/faJira"; +export { definition as faJoget } from "@fortawesome/free-brands-svg-icons/faJoget"; +export { definition as faJoomla } from "@fortawesome/free-brands-svg-icons/faJoomla"; +export { definition as faJs } from "@fortawesome/free-brands-svg-icons/faJs"; +export { definition as faJsSquare } from "@fortawesome/free-brands-svg-icons/faJsSquare"; +export { definition as faJsfiddle } from "@fortawesome/free-brands-svg-icons/faJsfiddle"; +export { definition as faJxl } from "@fortawesome/free-brands-svg-icons/faJxl"; +export { definition as faKaggle } from "@fortawesome/free-brands-svg-icons/faKaggle"; +export { definition as faKeybase } from "@fortawesome/free-brands-svg-icons/faKeybase"; +export { definition as faKeycdn } from "@fortawesome/free-brands-svg-icons/faKeycdn"; +export { definition as faKickstarter } from "@fortawesome/free-brands-svg-icons/faKickstarter"; +export { definition as faKickstarterK } from "@fortawesome/free-brands-svg-icons/faKickstarterK"; +export { definition as faKorvue } from "@fortawesome/free-brands-svg-icons/faKorvue"; +export { definition as faLaravel } from "@fortawesome/free-brands-svg-icons/faLaravel"; +export { definition as faLastfm } from "@fortawesome/free-brands-svg-icons/faLastfm"; +export { definition as faLastfmSquare } from "@fortawesome/free-brands-svg-icons/faLastfmSquare"; +export { definition as faLeanpub } from "@fortawesome/free-brands-svg-icons/faLeanpub"; +export { definition as faLess } from "@fortawesome/free-brands-svg-icons/faLess"; +export { definition as faLetterboxd } from "@fortawesome/free-brands-svg-icons/faLetterboxd"; +export { definition as faLine } from "@fortawesome/free-brands-svg-icons/faLine"; +export { definition as faLinkedin } from "@fortawesome/free-brands-svg-icons/faLinkedin"; +export { definition as faLinkedinIn } from "@fortawesome/free-brands-svg-icons/faLinkedinIn"; +export { definition as faLinode } from "@fortawesome/free-brands-svg-icons/faLinode"; +export { definition as faLinux } from "@fortawesome/free-brands-svg-icons/faLinux"; +export { definition as faLyft } from "@fortawesome/free-brands-svg-icons/faLyft"; +export { definition as faMagento } from "@fortawesome/free-brands-svg-icons/faMagento"; +export { definition as faMailchimp } from "@fortawesome/free-brands-svg-icons/faMailchimp"; +export { definition as faMandalorian } from "@fortawesome/free-brands-svg-icons/faMandalorian"; +export { definition as faMarkdown } from "@fortawesome/free-brands-svg-icons/faMarkdown"; +export { definition as faMastodon } from "@fortawesome/free-brands-svg-icons/faMastodon"; +export { definition as faMaxcdn } from "@fortawesome/free-brands-svg-icons/faMaxcdn"; +export { definition as faMdb } from "@fortawesome/free-brands-svg-icons/faMdb"; +export { definition as faMedapps } from "@fortawesome/free-brands-svg-icons/faMedapps"; +export { definition as faMedium } from "@fortawesome/free-brands-svg-icons/faMedium"; +export { definition as faMediumM } from "@fortawesome/free-brands-svg-icons/faMediumM"; +export { definition as faMedrt } from "@fortawesome/free-brands-svg-icons/faMedrt"; +export { definition as faMeetup } from "@fortawesome/free-brands-svg-icons/faMeetup"; +export { definition as faMegaport } from "@fortawesome/free-brands-svg-icons/faMegaport"; +export { definition as faMendeley } from "@fortawesome/free-brands-svg-icons/faMendeley"; +export { definition as faMeta } from "@fortawesome/free-brands-svg-icons/faMeta"; +export { definition as faMicroblog } from "@fortawesome/free-brands-svg-icons/faMicroblog"; +export { definition as faMicrosoft } from "@fortawesome/free-brands-svg-icons/faMicrosoft"; +export { definition as faMintbit } from "@fortawesome/free-brands-svg-icons/faMintbit"; +export { definition as faMix } from "@fortawesome/free-brands-svg-icons/faMix"; +export { definition as faMixcloud } from "@fortawesome/free-brands-svg-icons/faMixcloud"; +export { definition as faMixer } from "@fortawesome/free-brands-svg-icons/faMixer"; +export { definition as faMizuni } from "@fortawesome/free-brands-svg-icons/faMizuni"; +export { definition as faModx } from "@fortawesome/free-brands-svg-icons/faModx"; +export { definition as faMonero } from "@fortawesome/free-brands-svg-icons/faMonero"; +export { definition as faNapster } from "@fortawesome/free-brands-svg-icons/faNapster"; +export { definition as faNeos } from "@fortawesome/free-brands-svg-icons/faNeos"; +export { definition as faNfcDirectional } from "@fortawesome/free-brands-svg-icons/faNfcDirectional"; +export { definition as faNfcSymbol } from "@fortawesome/free-brands-svg-icons/faNfcSymbol"; +export { definition as faNimblr } from "@fortawesome/free-brands-svg-icons/faNimblr"; +export { definition as faNode } from "@fortawesome/free-brands-svg-icons/faNode"; +export { definition as faNodeJs } from "@fortawesome/free-brands-svg-icons/faNodeJs"; +export { definition as faNpm } from "@fortawesome/free-brands-svg-icons/faNpm"; +export { definition as faNs8 } from "@fortawesome/free-brands-svg-icons/faNs8"; +export { definition as faNutritionix } from "@fortawesome/free-brands-svg-icons/faNutritionix"; +export { definition as faOctopusDeploy } from "@fortawesome/free-brands-svg-icons/faOctopusDeploy"; +export { definition as faOdnoklassniki } from "@fortawesome/free-brands-svg-icons/faOdnoklassniki"; +export { definition as faOdnoklassnikiSquare } from "@fortawesome/free-brands-svg-icons/faOdnoklassnikiSquare"; +export { definition as faOdysee } from "@fortawesome/free-brands-svg-icons/faOdysee"; +export { definition as faOldRepublic } from "@fortawesome/free-brands-svg-icons/faOldRepublic"; +export { definition as faOpencart } from "@fortawesome/free-brands-svg-icons/faOpencart"; +export { definition as faOpenid } from "@fortawesome/free-brands-svg-icons/faOpenid"; +export { definition as faOpensuse } from "@fortawesome/free-brands-svg-icons/faOpensuse"; +export { definition as faOpera } from "@fortawesome/free-brands-svg-icons/faOpera"; +export { definition as faOptinMonster } from "@fortawesome/free-brands-svg-icons/faOptinMonster"; +export { definition as faOrcid } from "@fortawesome/free-brands-svg-icons/faOrcid"; +export { definition as faOsi } from "@fortawesome/free-brands-svg-icons/faOsi"; +export { definition as faPadlet } from "@fortawesome/free-brands-svg-icons/faPadlet"; +export { definition as faPage4 } from "@fortawesome/free-brands-svg-icons/faPage4"; +export { definition as faPagelines } from "@fortawesome/free-brands-svg-icons/faPagelines"; +export { definition as faPalfed } from "@fortawesome/free-brands-svg-icons/faPalfed"; +export { definition as faPatreon } from "@fortawesome/free-brands-svg-icons/faPatreon"; +export { definition as faPaypal } from "@fortawesome/free-brands-svg-icons/faPaypal"; +export { definition as faPerbyte } from "@fortawesome/free-brands-svg-icons/faPerbyte"; +export { definition as faPeriscope } from "@fortawesome/free-brands-svg-icons/faPeriscope"; +export { definition as faPhabricator } from "@fortawesome/free-brands-svg-icons/faPhabricator"; +export { definition as faPhoenixFramework } from "@fortawesome/free-brands-svg-icons/faPhoenixFramework"; +export { definition as faPhoenixSquadron } from "@fortawesome/free-brands-svg-icons/faPhoenixSquadron"; +export { definition as faPhp } from "@fortawesome/free-brands-svg-icons/faPhp"; +export { definition as faPiedPiper } from "@fortawesome/free-brands-svg-icons/faPiedPiper"; +export { definition as faPiedPiperAlt } from "@fortawesome/free-brands-svg-icons/faPiedPiperAlt"; +export { definition as faPiedPiperHat } from "@fortawesome/free-brands-svg-icons/faPiedPiperHat"; +export { definition as faPiedPiperPp } from "@fortawesome/free-brands-svg-icons/faPiedPiperPp"; +export { definition as faPiedPiperSquare } from "@fortawesome/free-brands-svg-icons/faPiedPiperSquare"; +export { definition as faPinterest } from "@fortawesome/free-brands-svg-icons/faPinterest"; +export { definition as faPinterestP } from "@fortawesome/free-brands-svg-icons/faPinterestP"; +export { definition as faPinterestSquare } from "@fortawesome/free-brands-svg-icons/faPinterestSquare"; +export { definition as faPix } from "@fortawesome/free-brands-svg-icons/faPix"; +export { definition as faPixiv } from "@fortawesome/free-brands-svg-icons/faPixiv"; +export { definition as faPlaystation } from "@fortawesome/free-brands-svg-icons/faPlaystation"; +export { definition as faProductHunt } from "@fortawesome/free-brands-svg-icons/faProductHunt"; +export { definition as faPushed } from "@fortawesome/free-brands-svg-icons/faPushed"; +export { definition as faPython } from "@fortawesome/free-brands-svg-icons/faPython"; +export { definition as faQq } from "@fortawesome/free-brands-svg-icons/faQq"; +export { definition as faQuinscape } from "@fortawesome/free-brands-svg-icons/faQuinscape"; +export { definition as faQuora } from "@fortawesome/free-brands-svg-icons/faQuora"; +export { definition as faRProject } from "@fortawesome/free-brands-svg-icons/faRProject"; +export { definition as faRaspberryPi } from "@fortawesome/free-brands-svg-icons/faRaspberryPi"; +export { definition as faRavelry } from "@fortawesome/free-brands-svg-icons/faRavelry"; +export { definition as faReact } from "@fortawesome/free-brands-svg-icons/faReact"; +export { definition as faReacteurope } from "@fortawesome/free-brands-svg-icons/faReacteurope"; +export { definition as faReadme } from "@fortawesome/free-brands-svg-icons/faReadme"; +export { definition as faRebel } from "@fortawesome/free-brands-svg-icons/faRebel"; +export { definition as faRedRiver } from "@fortawesome/free-brands-svg-icons/faRedRiver"; +export { definition as faReddit } from "@fortawesome/free-brands-svg-icons/faReddit"; +export { definition as faRedditAlien } from "@fortawesome/free-brands-svg-icons/faRedditAlien"; +export { definition as faRedditSquare } from "@fortawesome/free-brands-svg-icons/faRedditSquare"; +export { definition as faRedhat } from "@fortawesome/free-brands-svg-icons/faRedhat"; +export { definition as faRendact } from "@fortawesome/free-brands-svg-icons/faRendact"; +export { definition as faRenren } from "@fortawesome/free-brands-svg-icons/faRenren"; +export { definition as faReplyd } from "@fortawesome/free-brands-svg-icons/faReplyd"; +export { definition as faResearchgate } from "@fortawesome/free-brands-svg-icons/faResearchgate"; +export { definition as faResolving } from "@fortawesome/free-brands-svg-icons/faResolving"; +export { definition as faRev } from "@fortawesome/free-brands-svg-icons/faRev"; +export { definition as faRocketchat } from "@fortawesome/free-brands-svg-icons/faRocketchat"; +export { definition as faRockrms } from "@fortawesome/free-brands-svg-icons/faRockrms"; +export { definition as faRust } from "@fortawesome/free-brands-svg-icons/faRust"; +export { definition as faSafari } from "@fortawesome/free-brands-svg-icons/faSafari"; +export { definition as faSalesforce } from "@fortawesome/free-brands-svg-icons/faSalesforce"; +export { definition as faSass } from "@fortawesome/free-brands-svg-icons/faSass"; +export { definition as faSchlix } from "@fortawesome/free-brands-svg-icons/faSchlix"; +export { definition as faScreenpal } from "@fortawesome/free-brands-svg-icons/faScreenpal"; +export { definition as faScribd } from "@fortawesome/free-brands-svg-icons/faScribd"; +export { definition as faSearchengin } from "@fortawesome/free-brands-svg-icons/faSearchengin"; +export { definition as faSellcast } from "@fortawesome/free-brands-svg-icons/faSellcast"; +export { definition as faSellsy } from "@fortawesome/free-brands-svg-icons/faSellsy"; +export { definition as faServicestack } from "@fortawesome/free-brands-svg-icons/faServicestack"; +export { definition as faShirtsinbulk } from "@fortawesome/free-brands-svg-icons/faShirtsinbulk"; +export { definition as faShoelace } from "@fortawesome/free-brands-svg-icons/faShoelace"; +export { definition as faShopify } from "@fortawesome/free-brands-svg-icons/faShopify"; +export { definition as faShopware } from "@fortawesome/free-brands-svg-icons/faShopware"; +export { definition as faSignalMessenger } from "@fortawesome/free-brands-svg-icons/faSignalMessenger"; +export { definition as faSimplybuilt } from "@fortawesome/free-brands-svg-icons/faSimplybuilt"; +export { definition as faSistrix } from "@fortawesome/free-brands-svg-icons/faSistrix"; +export { definition as faSith } from "@fortawesome/free-brands-svg-icons/faSith"; +export { definition as faSitrox } from "@fortawesome/free-brands-svg-icons/faSitrox"; +export { definition as faSketch } from "@fortawesome/free-brands-svg-icons/faSketch"; +export { definition as faSkyatlas } from "@fortawesome/free-brands-svg-icons/faSkyatlas"; +export { definition as faSkype } from "@fortawesome/free-brands-svg-icons/faSkype"; +export { definition as faSlack } from "@fortawesome/free-brands-svg-icons/faSlack"; +export { definition as faSlackHash } from "@fortawesome/free-brands-svg-icons/faSlackHash"; +export { definition as faSlideshare } from "@fortawesome/free-brands-svg-icons/faSlideshare"; +export { definition as faSnapchat } from "@fortawesome/free-brands-svg-icons/faSnapchat"; +export { definition as faSnapchatGhost } from "@fortawesome/free-brands-svg-icons/faSnapchatGhost"; +export { definition as faSnapchatSquare } from "@fortawesome/free-brands-svg-icons/faSnapchatSquare"; +export { definition as faSoundcloud } from "@fortawesome/free-brands-svg-icons/faSoundcloud"; +export { definition as faSourcetree } from "@fortawesome/free-brands-svg-icons/faSourcetree"; +export { definition as faSpaceAwesome } from "@fortawesome/free-brands-svg-icons/faSpaceAwesome"; +export { definition as faSpeakap } from "@fortawesome/free-brands-svg-icons/faSpeakap"; +export { definition as faSpeakerDeck } from "@fortawesome/free-brands-svg-icons/faSpeakerDeck"; +export { definition as faSpotify } from "@fortawesome/free-brands-svg-icons/faSpotify"; +export { definition as faSquareBehance } from "@fortawesome/free-brands-svg-icons/faSquareBehance"; +export { definition as faSquareBluesky } from "@fortawesome/free-brands-svg-icons/faSquareBluesky"; +export { definition as faSquareDribbble } from "@fortawesome/free-brands-svg-icons/faSquareDribbble"; +export { definition as faSquareFacebook } from "@fortawesome/free-brands-svg-icons/faSquareFacebook"; +export { definition as faSquareFontAwesome } from "@fortawesome/free-brands-svg-icons/faSquareFontAwesome"; +export { definition as faSquareFontAwesomeStroke } from "@fortawesome/free-brands-svg-icons/faSquareFontAwesomeStroke"; +export { definition as faSquareGit } from "@fortawesome/free-brands-svg-icons/faSquareGit"; +export { definition as faSquareGithub } from "@fortawesome/free-brands-svg-icons/faSquareGithub"; +export { definition as faSquareGitlab } from "@fortawesome/free-brands-svg-icons/faSquareGitlab"; +export { definition as faSquareGooglePlus } from "@fortawesome/free-brands-svg-icons/faSquareGooglePlus"; +export { definition as faSquareHackerNews } from "@fortawesome/free-brands-svg-icons/faSquareHackerNews"; +export { definition as faSquareInstagram } from "@fortawesome/free-brands-svg-icons/faSquareInstagram"; +export { definition as faSquareJs } from "@fortawesome/free-brands-svg-icons/faSquareJs"; +export { definition as faSquareKickstarter } from "@fortawesome/free-brands-svg-icons/faSquareKickstarter"; +export { definition as faSquareLastfm } from "@fortawesome/free-brands-svg-icons/faSquareLastfm"; +export { definition as faSquareLetterboxd } from "@fortawesome/free-brands-svg-icons/faSquareLetterboxd"; +export { definition as faSquareOdnoklassniki } from "@fortawesome/free-brands-svg-icons/faSquareOdnoklassniki"; +export { definition as faSquarePiedPiper } from "@fortawesome/free-brands-svg-icons/faSquarePiedPiper"; +export { definition as faSquarePinterest } from "@fortawesome/free-brands-svg-icons/faSquarePinterest"; +export { definition as faSquareReddit } from "@fortawesome/free-brands-svg-icons/faSquareReddit"; +export { definition as faSquareSnapchat } from "@fortawesome/free-brands-svg-icons/faSquareSnapchat"; +export { definition as faSquareSteam } from "@fortawesome/free-brands-svg-icons/faSquareSteam"; +export { definition as faSquareThreads } from "@fortawesome/free-brands-svg-icons/faSquareThreads"; +export { definition as faSquareTumblr } from "@fortawesome/free-brands-svg-icons/faSquareTumblr"; +export { definition as faSquareTwitter } from "@fortawesome/free-brands-svg-icons/faSquareTwitter"; +export { definition as faSquareUpwork } from "@fortawesome/free-brands-svg-icons/faSquareUpwork"; +export { definition as faSquareViadeo } from "@fortawesome/free-brands-svg-icons/faSquareViadeo"; +export { definition as faSquareVimeo } from "@fortawesome/free-brands-svg-icons/faSquareVimeo"; +export { definition as faSquareWebAwesome } from "@fortawesome/free-brands-svg-icons/faSquareWebAwesome"; +export { definition as faSquareWebAwesomeStroke } from "@fortawesome/free-brands-svg-icons/faSquareWebAwesomeStroke"; +export { definition as faSquareWhatsapp } from "@fortawesome/free-brands-svg-icons/faSquareWhatsapp"; +export { definition as faSquareXTwitter } from "@fortawesome/free-brands-svg-icons/faSquareXTwitter"; +export { definition as faSquareXing } from "@fortawesome/free-brands-svg-icons/faSquareXing"; +export { definition as faSquareYoutube } from "@fortawesome/free-brands-svg-icons/faSquareYoutube"; +export { definition as faSquarespace } from "@fortawesome/free-brands-svg-icons/faSquarespace"; +export { definition as faStackExchange } from "@fortawesome/free-brands-svg-icons/faStackExchange"; +export { definition as faStackOverflow } from "@fortawesome/free-brands-svg-icons/faStackOverflow"; +export { definition as faStackpath } from "@fortawesome/free-brands-svg-icons/faStackpath"; +export { definition as faStaylinked } from "@fortawesome/free-brands-svg-icons/faStaylinked"; +export { definition as faSteam } from "@fortawesome/free-brands-svg-icons/faSteam"; +export { definition as faSteamSquare } from "@fortawesome/free-brands-svg-icons/faSteamSquare"; +export { definition as faSteamSymbol } from "@fortawesome/free-brands-svg-icons/faSteamSymbol"; +export { definition as faStickerMule } from "@fortawesome/free-brands-svg-icons/faStickerMule"; +export { definition as faStrava } from "@fortawesome/free-brands-svg-icons/faStrava"; +export { definition as faStripe } from "@fortawesome/free-brands-svg-icons/faStripe"; +export { definition as faStripeS } from "@fortawesome/free-brands-svg-icons/faStripeS"; +export { definition as faStubber } from "@fortawesome/free-brands-svg-icons/faStubber"; +export { definition as faStudiovinari } from "@fortawesome/free-brands-svg-icons/faStudiovinari"; +export { definition as faStumbleupon } from "@fortawesome/free-brands-svg-icons/faStumbleupon"; +export { definition as faStumbleuponCircle } from "@fortawesome/free-brands-svg-icons/faStumbleuponCircle"; +export { definition as faSuperpowers } from "@fortawesome/free-brands-svg-icons/faSuperpowers"; +export { definition as faSupple } from "@fortawesome/free-brands-svg-icons/faSupple"; +export { definition as faSuse } from "@fortawesome/free-brands-svg-icons/faSuse"; +export { definition as faSwift } from "@fortawesome/free-brands-svg-icons/faSwift"; +export { definition as faSymfony } from "@fortawesome/free-brands-svg-icons/faSymfony"; +export { definition as faTeamspeak } from "@fortawesome/free-brands-svg-icons/faTeamspeak"; +export { definition as faTelegram } from "@fortawesome/free-brands-svg-icons/faTelegram"; +export { definition as faTelegramPlane } from "@fortawesome/free-brands-svg-icons/faTelegramPlane"; +export { definition as faTencentWeibo } from "@fortawesome/free-brands-svg-icons/faTencentWeibo"; +export { definition as faTheRedYeti } from "@fortawesome/free-brands-svg-icons/faTheRedYeti"; +export { definition as faThemeco } from "@fortawesome/free-brands-svg-icons/faThemeco"; +export { definition as faThemeisle } from "@fortawesome/free-brands-svg-icons/faThemeisle"; +export { definition as faThinkPeaks } from "@fortawesome/free-brands-svg-icons/faThinkPeaks"; +export { definition as faThreads } from "@fortawesome/free-brands-svg-icons/faThreads"; +export { definition as faTiktok } from "@fortawesome/free-brands-svg-icons/faTiktok"; +export { definition as faTradeFederation } from "@fortawesome/free-brands-svg-icons/faTradeFederation"; +export { definition as faTrello } from "@fortawesome/free-brands-svg-icons/faTrello"; +export { definition as faTumblr } from "@fortawesome/free-brands-svg-icons/faTumblr"; +export { definition as faTumblrSquare } from "@fortawesome/free-brands-svg-icons/faTumblrSquare"; +export { definition as faTwitch } from "@fortawesome/free-brands-svg-icons/faTwitch"; +export { definition as faTwitter } from "@fortawesome/free-brands-svg-icons/faTwitter"; +export { definition as faTwitterSquare } from "@fortawesome/free-brands-svg-icons/faTwitterSquare"; +export { definition as faTypo3 } from "@fortawesome/free-brands-svg-icons/faTypo3"; +export { definition as faUber } from "@fortawesome/free-brands-svg-icons/faUber"; +export { definition as faUbuntu } from "@fortawesome/free-brands-svg-icons/faUbuntu"; +export { definition as faUikit } from "@fortawesome/free-brands-svg-icons/faUikit"; +export { definition as faUmbraco } from "@fortawesome/free-brands-svg-icons/faUmbraco"; +export { definition as faUncharted } from "@fortawesome/free-brands-svg-icons/faUncharted"; +export { definition as faUniregistry } from "@fortawesome/free-brands-svg-icons/faUniregistry"; +export { definition as faUnity } from "@fortawesome/free-brands-svg-icons/faUnity"; +export { definition as faUnsplash } from "@fortawesome/free-brands-svg-icons/faUnsplash"; +export { definition as faUntappd } from "@fortawesome/free-brands-svg-icons/faUntappd"; +export { definition as faUps } from "@fortawesome/free-brands-svg-icons/faUps"; +export { definition as faUpwork } from "@fortawesome/free-brands-svg-icons/faUpwork"; +export { definition as faUsb } from "@fortawesome/free-brands-svg-icons/faUsb"; +export { definition as faUsps } from "@fortawesome/free-brands-svg-icons/faUsps"; +export { definition as faUssunnah } from "@fortawesome/free-brands-svg-icons/faUssunnah"; +export { definition as faVaadin } from "@fortawesome/free-brands-svg-icons/faVaadin"; +export { definition as faViacoin } from "@fortawesome/free-brands-svg-icons/faViacoin"; +export { definition as faViadeo } from "@fortawesome/free-brands-svg-icons/faViadeo"; +export { definition as faViadeoSquare } from "@fortawesome/free-brands-svg-icons/faViadeoSquare"; +export { definition as faViber } from "@fortawesome/free-brands-svg-icons/faViber"; +export { definition as faVimeo } from "@fortawesome/free-brands-svg-icons/faVimeo"; +export { definition as faVimeoSquare } from "@fortawesome/free-brands-svg-icons/faVimeoSquare"; +export { definition as faVimeoV } from "@fortawesome/free-brands-svg-icons/faVimeoV"; +export { definition as faVine } from "@fortawesome/free-brands-svg-icons/faVine"; +export { definition as faVk } from "@fortawesome/free-brands-svg-icons/faVk"; +export { definition as faVnv } from "@fortawesome/free-brands-svg-icons/faVnv"; +export { definition as faVuejs } from "@fortawesome/free-brands-svg-icons/faVuejs"; +export { definition as faWatchmanMonitoring } from "@fortawesome/free-brands-svg-icons/faWatchmanMonitoring"; +export { definition as faWaze } from "@fortawesome/free-brands-svg-icons/faWaze"; +export { definition as faWebflow } from "@fortawesome/free-brands-svg-icons/faWebflow"; +export { definition as faWeebly } from "@fortawesome/free-brands-svg-icons/faWeebly"; +export { definition as faWeibo } from "@fortawesome/free-brands-svg-icons/faWeibo"; +export { definition as faWeixin } from "@fortawesome/free-brands-svg-icons/faWeixin"; +export { definition as faWhatsapp } from "@fortawesome/free-brands-svg-icons/faWhatsapp"; +export { definition as faWhatsappSquare } from "@fortawesome/free-brands-svg-icons/faWhatsappSquare"; +export { definition as faWhmcs } from "@fortawesome/free-brands-svg-icons/faWhmcs"; +export { definition as faWikipediaW } from "@fortawesome/free-brands-svg-icons/faWikipediaW"; +export { definition as faWindows } from "@fortawesome/free-brands-svg-icons/faWindows"; +export { definition as faWirsindhandwerk } from "@fortawesome/free-brands-svg-icons/faWirsindhandwerk"; +export { definition as faWix } from "@fortawesome/free-brands-svg-icons/faWix"; +export { definition as faWizardsOfTheCoast } from "@fortawesome/free-brands-svg-icons/faWizardsOfTheCoast"; +export { definition as faWodu } from "@fortawesome/free-brands-svg-icons/faWodu"; +export { definition as faWolfPackBattalion } from "@fortawesome/free-brands-svg-icons/faWolfPackBattalion"; +export { definition as faWordpress } from "@fortawesome/free-brands-svg-icons/faWordpress"; +export { definition as faWordpressSimple } from "@fortawesome/free-brands-svg-icons/faWordpressSimple"; +export { definition as faWpbeginner } from "@fortawesome/free-brands-svg-icons/faWpbeginner"; +export { definition as faWpexplorer } from "@fortawesome/free-brands-svg-icons/faWpexplorer"; +export { definition as faWpforms } from "@fortawesome/free-brands-svg-icons/faWpforms"; +export { definition as faWpressr } from "@fortawesome/free-brands-svg-icons/faWpressr"; +export { definition as faWsh } from "@fortawesome/free-brands-svg-icons/faWsh"; +export { definition as faXTwitter } from "@fortawesome/free-brands-svg-icons/faXTwitter"; +export { definition as faXbox } from "@fortawesome/free-brands-svg-icons/faXbox"; +export { definition as faXing } from "@fortawesome/free-brands-svg-icons/faXing"; +export { definition as faXingSquare } from "@fortawesome/free-brands-svg-icons/faXingSquare"; +export { definition as faYCombinator } from "@fortawesome/free-brands-svg-icons/faYCombinator"; +export { definition as faYahoo } from "@fortawesome/free-brands-svg-icons/faYahoo"; +export { definition as faYammer } from "@fortawesome/free-brands-svg-icons/faYammer"; +export { definition as faYandex } from "@fortawesome/free-brands-svg-icons/faYandex"; +export { definition as faYandexInternational } from "@fortawesome/free-brands-svg-icons/faYandexInternational"; +export { definition as faYarn } from "@fortawesome/free-brands-svg-icons/faYarn"; +export { definition as faYelp } from "@fortawesome/free-brands-svg-icons/faYelp"; +export { definition as faYoast } from "@fortawesome/free-brands-svg-icons/faYoast"; +export { definition as faYoutube } from "@fortawesome/free-brands-svg-icons/faYoutube"; +export { definition as faYoutubeSquare } from "@fortawesome/free-brands-svg-icons/faYoutubeSquare"; +export { definition as faZhihu } from "@fortawesome/free-brands-svg-icons/faZhihu"; +export { definition as fa00 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as fa100 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as fa360Degrees } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAbacus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAccentGrave } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAcorn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAirConditioner } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAirplay } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlarmClock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlarmExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlarmPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlarmSnooze } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlbum } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlbumCirclePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlbumCircleUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlbumCollection } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlbumCollectionCirclePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlbumCollectionCircleUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlicorn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlien } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlien8bit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlienMonster } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlignSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAmpGuitar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAmpersand } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAnalytics } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAngel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAngle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAngle90 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAnglesUpDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAnt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faApartment } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAperture } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faApostrophe } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAppleCore } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAppleCrate } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltFromBottom } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltFromLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltFromRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltFromTop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltSquareDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltSquareLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltSquareRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltSquareUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltToBottom } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltToLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltToRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltToTop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownBigSmall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownFromArc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownFromBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownFromDottedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownFromLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownLeftAndArrowUpRightToCenter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownSmallBig } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownSquareTriangle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownToArc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownToBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownToDottedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownToSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownTriangleSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowFromBottom } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowFromLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowFromRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowFromTop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowLeftFromArc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowLeftFromBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowLeftFromLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowLeftLongToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowLeftToArc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowLeftToBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowLeftToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowProgress } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowRightFromArc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowRightFromLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowRightLongToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowRightToArc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowRightToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowSquareDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowSquareLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowSquareRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowSquareUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowToBottom } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowToLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowToRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowToTop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowTurnDownLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowTurnDownRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowTurnLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowTurnLeftDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowTurnLeftUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowTurnRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpBigSmall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpFromArc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpFromDottedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpFromLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpFromSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpLeftFromCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpRightAndArrowDownLeftFromCenter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpSmallBig } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpSquareTriangle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpToArc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpToBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpToDottedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpTriangleSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsCross } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsFromDottedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsFromLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsMaximize } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsMinimize } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsRepeat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsRepeat1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsRetweet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsRotateReverse } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsToDottedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAtomAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAtomSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAudioDescriptionSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAvocado } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAwardSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAxe } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAxeBattle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBackpack } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBadge } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBadgeCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBadgeDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBadgePercent } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBadgeSheriff } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBadgerHoney } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBadminton } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBagSeedling } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBagShoppingMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBagShoppingPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBagel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBagsShopping } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBaguette } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBallPile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBalloon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBalloons } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBallot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBallotCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBanBug } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBanParking } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBanana } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBanjo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBarcodeAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBarcodeRead } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBarcodeScan } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBarnSilo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBarsFilter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBarsSort } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBasketShoppingMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBasketShoppingPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBasketShoppingSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBasketballHoop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBattery1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBatteryBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBatteryExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBatteryLow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBatterySlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBedAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBedBunk } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBedEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBedFront } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBee } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBeerFoam } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBeerMug } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBellExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBellOn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBellPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBellRing } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBellSchool } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBellSchoolSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBells } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBenchTree } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBetamax } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBikingMountain } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBillboard } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBinBottles } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBinBottlesRecycle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBinRecycle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBinary } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBinaryCircleCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBinaryLock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBinarySlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBird } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlanket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlanketFire } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlinds } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlindsOpen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlindsRaised } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlockBrick } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlockBrickFire } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlockQuestion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlockQuote } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlueberries } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoltAuto } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoltSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoneBreak } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookArrowRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookBlank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookCircleArrowRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookCircleArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookCopy } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookFont } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookLaw } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookOpenAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookOpenCover } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookSection } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookSparkles } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookSpells } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookmarkCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookmarkSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBooks } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBooksMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoombox } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBootHeeled } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoothCurtain } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBorderBottom } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBorderBottomRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBorderCenterH } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBorderCenterV } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBorderInner } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBorderLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBorderOuter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBorderRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBorderStyleAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBorderTop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBottleBaby } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowArrow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlChopsticks } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlChopsticksNoodles } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlHot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlSalad } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlScoop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlScoops } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlShavedIce } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlSoftServe } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlSpoon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlingBallPin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlingPins } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxBallot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxCircleCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxFragile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxFull } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxOpenFull } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxTaped } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxUsd } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxingGlove } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketCurly } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketCurlyLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketCurlyRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketRound } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketRoundRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketSquareRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBrackets } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketsCurly } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketsRound } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketsSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBrainArrowCurvedRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBrainCircuit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBrakeWarning } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBreadLoaf } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBreadSliceButter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBridgeSuspension } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBriefcaseArrowRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBriefcaseBlank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBrightness } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBrightnessLow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBringForward } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBringFront } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBroccoli } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBroomWide } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBrowser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBrowsers } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBuildingMagnifyingGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBuildingMemo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBuildings } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBulldozer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBullseyeArrow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBullseyePointer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBuoy } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBuoyMooring } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBurgerCheese } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBurgerFries } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBurgerGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBurgerLettuce } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBurgerSoda } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBurrito } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBusSchool } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBusinessFront } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faButter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCabin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCabinetFiling } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCactus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCaduceus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCakeSlice } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalculatorAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalculatorSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarCircleExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarCircleMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarCirclePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarCircleUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarClock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarDownload } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarEdit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarImage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarLines } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarLinesPen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarNote } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarPen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarRange } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarStar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarTime } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarUpload } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarUsers } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendars } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCamcorder } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCameraCctv } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCameraCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCameraHome } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCameraMovie } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCameraPolaroid } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCameraSecurity } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCameraSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCameraViewfinder } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCameraWeb } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCameraWebSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCampfire } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCanFood } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCandleHolder } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCandy } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCandyBar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCandyCorn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCannon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarBuilding } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarBump } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarBus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarCircleBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarGarage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarMechanic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarMirrors } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarSideBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarTilt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarWash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarWrench } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCaravanAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCaravanSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCardClub } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCardDiamond } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCardHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCardSpade } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCards } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCardsBlank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCaretCircleDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCaretCircleLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCaretCircleRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCaretCircleUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCars } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartCircleArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartCircleArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartCircleCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartCircleExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartCirclePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartCircleXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartFlatbedBoxes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartFlatbedEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartShoppingFast } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCassetteBetamax } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCassetteTape } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCassetteVhs } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCastle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCatSpace } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCauldron } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCctv } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChainHorizontal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChainHorizontalSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChairOffice } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChampagneGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartBullet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartCandlestick } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartKanban } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartLineDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartLineUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartLineUpDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartMixed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartMixedUpCircleCurrency } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartMixedUpCircleDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartNetwork } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartPieAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartPieSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartPieSimpleCircleCurrency } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartPieSimpleCircleDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartPyramid } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartRadar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartScatter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartScatter3d } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartScatterBubble } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartSimpleHorizontal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartTreeMap } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartWaterfall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCheeseSwiss } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCheeseburger } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCherries } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessBishopAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessBishopPiece } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessClock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessClockAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessClockFlip } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessKingAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessKingPiece } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessKnightAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessKnightPiece } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessPawnAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessPawnPiece } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessQueenAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessQueenPiece } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessRookAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessRookPiece } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChestnut } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronDoubleDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronDoubleLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronDoubleRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronDoubleUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronSquareDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronSquareLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronSquareRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronSquareUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronsDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronsLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronsRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronsUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChfSign } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChimney } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChocolateBar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChopsticks } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircle0 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircle1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircle2 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircle3 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircle4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircle5 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircle6 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircle7 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircle8 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircle9 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleA } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleAmpersand } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleArrowDownLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleArrowDownRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleArrowUpLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleArrowUpRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleB } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleBookOpen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleBookmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleC } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleCalendar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleCamera } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleCaretDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleCaretLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleCaretRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleCaretUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleD } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleDashed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleDivide } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleDownLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleDownRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleE } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleEllipsis } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleEllipsisVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleEnvelope } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleEuro } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleExclamationCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleF } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleG } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleGf } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleHalf } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleI } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleJ } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleK } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleL } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleLocationArrow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleM } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleMicrophone } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleMicrophoneLines } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleN } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleO } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleP } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleParking } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCirclePhone } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCirclePhoneFlip } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCirclePhoneHangup } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleQ } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleQuarter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleQuarterStroke } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleQuarters } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleR } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleS } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleSmall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleSort } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleSortDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleSortUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleStar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleSterling } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleT } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleThreeQuarters } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleThreeQuartersStroke } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleTrash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleU } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleUpLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleUpRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleV } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleVideo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleW } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleWaveformLines } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleWifi } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleWifiCircleWifi } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleWifiGroup } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleX } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleY } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleYen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleZ } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCirclesOverlap } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCitrus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCitrusSlice } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClapperboardPlay } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClarinet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClawMarks } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClipboardListCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClipboardMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClipboardPrescription } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockDesk } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockEight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockEightThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockEleven } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockElevenThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockFive } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockFiveThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockFourThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockNine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockNineThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockOne } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockOneThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockSeven } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockSevenThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockSix } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockSixThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockTen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockTenThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockThree } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockThreeThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockTwelve } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockTwelveThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockTwo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockTwoThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClosedCaptioningSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClothesHanger } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudBinary } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudBoltMoon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudBoltSun } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudDrizzle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudFog } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudHail } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudHailMixed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudQuestion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudRainbow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudShowers } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudSleet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudSnow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudWord } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClouds } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudsMoon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudsSun } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClub } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoconut } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCodePullRequestClosed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCodePullRequestDraft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCodeSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoffeeBean } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoffeeBeans } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoffeePot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoffeeTogo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoffin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoffinCross } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoinBlank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoinFront } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoinVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faColon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faColumns3 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faComet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faComma } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommand } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltCaptions } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltDots } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltEdit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltImage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltLines } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltQuote } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltSmile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltText } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltTimes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentArrowUpRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentCaptions } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentCode } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentEdit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentImage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentLines } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentMiddle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentMiddleAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentMiddleTop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentMiddleTopAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentPen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentQuestion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentQuote } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentSmile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentText } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentTimes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentsAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentsAltDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentsQuestion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentsQuestionCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCompassSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCompressArrows } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCompressWide } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faComputerClassic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faComputerMouseScrollwheel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faComputerSpeaker } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faConstruction } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faContainerStorage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faConveyorBelt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faConveyorBeltAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faConveyorBeltArm } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faConveyorBeltBoxes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faConveyorBeltEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCorn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCorner } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCouchSmall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCourtSport } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCowbell } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCowbellCirclePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCowbellMore } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCrab } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCrateApple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCrateEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCreditCardBlank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCreditCardFront } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCreemee } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCricket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCricketBatBall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCroissant } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCrosshairsSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCrutches } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCrystalBall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCucumber } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCupStraw } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCupStrawSwoosh } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCupTogo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCupcake } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCurling } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCurlingStone } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCustard } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDagger } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDebug } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDeer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDeerRudolph } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDeleteRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDesktopArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDesktopCode } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDesktopMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDesktopSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDewpoint } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiagramCells } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiagramLeanCanvas } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiagramNested } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiagramPrevious } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiagramSankey } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiagramSubtask } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiagramVenn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDial } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDialHigh } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDialLow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDialMax } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDialMed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDialMedHigh } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDialMedLow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDialMin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDialOff } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiamondExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiamondHalf } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiamondHalfStroke } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiamonds4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiceD10 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiceD12 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiceD4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiceD8 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDinosaur } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiploma } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiscDrive } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDisplayArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDisplayChartUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDisplayChartUpCircleCurrency } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDisplayChartUpCircleDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDisplayCode } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDisplayMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDisplaySlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDistributeSpacingHorizontal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDistributeSpacingVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDitto } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDoNotEnter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDogLeashed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDollarCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDollarSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDollyEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDollyFlatbedAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDollyFlatbedEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDolphin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDonut } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDoughnut } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDownFromBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDownFromDottedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDownFromLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDownLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDownRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDownToBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDownToDottedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDownToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDrawCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDrawSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDreidel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDrone } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDroneAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDroneFront } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDropletDegree } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDropletPercent } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDrumstick } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDryer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDryerAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDryerHeat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDuck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEarMuffs } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEclipse } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEclipseAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEggFried } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEggplant } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faElephant } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEllipsisHAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEllipsisStroke } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEllipsisStrokeVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEllipsisVAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEmptySet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEngine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEngineExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEngineWarning } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEnvelopeBadge } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEnvelopeCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEnvelopeDot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEnvelopeOpenDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEnvelopes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEscalator } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faExcavator } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faExclamationSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faExpandArrows } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faExpandWide } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faExplodingHead } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEyeDropperFull } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEyeDropperHalf } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEyeEvil } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEyes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceAngryHorns } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceAnguished } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceAnxiousSweat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceAstonished } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceAwesome } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceBeamHandOverMouth } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceClouds } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceConfounded } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceConfused } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceCowboyHat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceDiagonalMouth } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceDisappointed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceDisguise } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceDotted } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceDowncastSweat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceDrooling } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceExhaling } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceExplode } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceExpressionless } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceEyesXmarks } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceFearful } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceFrownSlight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceGlasses } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceHandOverMouth } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceHandPeeking } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceHandYawn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceHeadBandage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceHoldingBackTears } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceHushed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceIcicles } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceKissClosedEyes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceLying } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceMask } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceMelting } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceMonocle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceNauseated } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceNoseSteam } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceParty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFacePensive } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFacePersevering } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFacePleading } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFacePouting } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceRaisedEyebrow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceRelieved } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSadSweat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSaluting } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceScream } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceShush } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSleeping } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSleepy } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSmileHalo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSmileHearts } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSmileHorns } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSmilePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSmileRelaxed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSmileTear } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSmileTongue } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSmileUpsideDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSmilingHands } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSmirking } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSpiralEyes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSunglasses } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSwear } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceThermometer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceThinking } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceTissue } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceTongueMoney } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceTongueSweat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceUnamused } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceViewfinder } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceVomit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceWeary } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceWoozy } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceWorried } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceZany } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceZipper } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFalafel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFamily } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFamilyDress } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFamilyPants } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFanTable } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFarm } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFence } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFerrisWheel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFieldHockey } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFieldHockeyStickBall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileAward } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileBinary } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileCad } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileCaretDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileCaretUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileCertificate } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileChartColumn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileChartLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileChartPie } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileCircleInfo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileDashedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileDoc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileEps } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileGif } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileJpg } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileLock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileMagnifyingGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileMov } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileMp3 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileMp4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilePlusMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilePng } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilePpt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileSearch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileSpreadsheet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileSvg } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileTimes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileVector } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileXls } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileXml } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileZip } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFiles } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilesMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilmAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilmCanister } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilmCannister } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilmSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilmSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilms } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilterList } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilterSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilters } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFireFlame } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFireHydrant } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFireSmoke } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFireplace } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFirewall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFishBones } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFishCooked } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFishingRod } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlagAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlagPennant } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlagSwallowtail } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlame } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlashlight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlaskGear } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlaskPoison } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlaskPotion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlaskRoundPoison } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlaskRoundPotion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlatbread } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlatbreadStuffed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFloppyDiskCircleArrowRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFloppyDiskCircleXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFloppyDiskPen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFloppyDiskTimes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFloppyDisks } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlower } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlowerDaffodil } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlowerTulip } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlute } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFluxCapacitor } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlyingDisc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFog } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderBookmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderCog } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderDownload } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderGear } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderGrid } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderImage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderMagnifyingGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderSearch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderTimes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderUpload } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolders } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFonduePot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFontCase } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFootballHelmet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFork } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faForkKnife } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faForklift } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFort } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFragile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFrame } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFrenchFries } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFrostyHead } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFunction } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGalaxy } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGalleryThumbnails } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGameBoard } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGameBoardAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGameBoardSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGameConsoleHandheld } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGameConsoleHandheldCrank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGamepadAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGamepadModern } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGarage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGarageCar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGarageOpen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGarlic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGasPumpSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGaugeCircleBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGaugeCircleMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGaugeCirclePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGaugeLow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGaugeMax } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGaugeMin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGaugeSimpleLow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGaugeSimpleMax } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGaugeSimpleMin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGaveDandy } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGearCode } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGearComplex } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGearComplexCode } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGif } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGiftCard } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGingerbreadMan } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlassChampagne } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlassCitrus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlassEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlassHalf } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlassHalfEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlassHalfFull } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlassWhiskeyRocks } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlassesAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlassesRound } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlobePointer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlobeSnow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlobeStand } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlobeWifi } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGloveBoxing } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGoalNet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGolfClub } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGolfFlagHole } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGramophone } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrapes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrate } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrateDroplet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrid } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrid2 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrid2Plus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrid3 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrid4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrid5 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGridDividers } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGridHorizontal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGridRound } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGridRound2 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGridRound2Plus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGridRound4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGridRound5 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrill } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrillFire } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrillHot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGripDots } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGripDotsVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGuitarElectric } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGuitars } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGunSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGunSquirt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faH1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faH2 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faH3 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faH4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faH5 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faH6 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHammerBrush } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHammerCrash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHammerWar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandBackPointDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandBackPointLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandBackPointRibbon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandBackPointRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandBackPointUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandFingersCrossed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandHoldingBox } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandHoldingCircleDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandHoldingMagic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandHoldingSeedling } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandHoldingSkull } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandHorns } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandLove } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandPointRibbon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandReceiving } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandWave } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandsHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandsHoldingDiamond } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandsHoldingDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandsHoldingHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandsUsd } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHashtagLock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHatBeach } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHatChef } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHatSanta } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHatWinter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHatWitch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeadSide } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeadSideBrain } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeadSideGear } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeadSideGoggles } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeadSideHeadphones } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeadSideHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeadSideMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeadVr } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeartCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeartHalf } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeartHalfAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeartHalfStroke } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeartRate } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeartSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHelmetBattle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHexagon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHexagonCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHexagonDivide } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHexagonExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHexagonImage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHexagonMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHexagonPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHexagonVerticalNft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHexagonVerticalNftSlanted } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHexagonXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHighDefinition } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHighlighterLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHockeyMask } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHockeyStickPuck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHockeySticks } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHomeBlank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHomeHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHoneyPot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHoodCloak } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHorizontalRule } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHorseSaddle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHose } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHoseReel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHospitals } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHourglassClock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseBlank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseBuilding } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseChimneyBlank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseChimneyHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseDay } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseFlood } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseLeave } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseNight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHousePersonArrive } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHousePersonDepart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHousePersonLeave } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHousePersonReturn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseReturn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseTree } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseTurret } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseWater } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseWindow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHumidity } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHundredPoints } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHydra } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHyphen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faIceSkate } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faIconsAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faImageLandscape } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faImagePolaroid } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faImagePolaroidUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faImageSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faImageUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faImagesUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInboxArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInboxArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInboxFull } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInboxIn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInboxOut } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInboxes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faIndustryAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faIndustryWindows } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInfoSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInhaler } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInputNumeric } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInputPipe } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInputText } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faIntegral } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInterrobang } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faIntersection } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInventory } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faIslandTreePalm } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faIslandTropical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faJackOLantern } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faJoystick } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faJug } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faJugBottle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKazoo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKerning } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKeySkeleton } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKeySkeletonLeftRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKeyboardBrightness } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKeyboardBrightnessLow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKeyboardDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKeyboardLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKeynote } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKidneys } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKite } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKiwiFruit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKnife } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKnifeKitchen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLacrosseStick } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLacrosseStickBall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLambda } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLamp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLampDesk } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLampFloor } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLampStreet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLandmarkMagnifyingGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLandscape } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLaptopArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLaptopBinary } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLaptopMobile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLaptopSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLasso } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLassoSparkles } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLayerGroupMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLayerGroupPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLayerMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLayerPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLeafHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLeafMaple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLeafOak } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLeafyGreen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLeftFromBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLeftFromLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLeftLongToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLeftToBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLeftToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightCeiling } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightEmergency } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightEmergencyOn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightSwitch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightSwitchOff } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightSwitchOn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightbulbCfl } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightbulbCflOn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightbulbDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightbulbExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightbulbExclamationOn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightbulbGear } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightbulbMessage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightbulbOn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightbulbSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLighthouse } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightsHoliday } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLineColumns } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLineHeight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLinkHorizontal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLinkHorizontalSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLinkSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLinkSimpleSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLips } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faListDropdown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faListMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faListRadio } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faListTimeline } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faListTree } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLoader } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLobster } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationCrosshairsSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationDotSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationPen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationPinSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationQuestion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationSmile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLockA } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLockAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLockHashtag } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLockKeyhole } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLockKeyholeOpen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLockOpenAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLollipop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLollypop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLoveseat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLuchador } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLuchadorMask } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMace } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMagnifyingGlassArrowsRotate } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMagnifyingGlassMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMagnifyingGlassPlay } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMagnifyingGlassWaveform } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMailbox } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMailboxFlagUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMakiRoll } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMakizushi } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMandolin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMango } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faManhole } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerAltSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerEdit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerQuestion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerSmile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerTimes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMaskLuchador } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMaskSnorkel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMeat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMegaphone } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMelon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMelonSlice } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMemo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMemoCircleCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMemoCircleInfo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMemoPad } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMerge } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageArrowUpRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageBot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageCaptions } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageCode } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageDots } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageEdit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageImage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageLines } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageMiddle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageMiddleTop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessagePen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessagePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageQuestion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageQuote } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageSmile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageSms } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageText } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageTimes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessages } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessagesDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessagesQuestion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessaging } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMeter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMeterBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMeterDroplet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMeterFire } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMicrochipAi } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMicrophoneCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMicrophoneCircleAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMicrophoneStand } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMicrowave } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMindShare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMinusHexagon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMinusLarge } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMinusOctagon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMistletoe } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMobileIphone } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMobileNotch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMobileSignal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMobileSignalOut } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoneyBillSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoneyBillSimpleWave } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoneyBillsAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoneyBillsSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoneyCheckDollarPen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoneyCheckEdit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoneyCheckEditAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoneyCheckPen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoneyFromBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoneySimpleFromBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMonitorHeartRate } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMonitorWaveform } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMonkey } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoonCloud } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoonOverSun } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoonStars } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoped } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMountains } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMouseAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMouseField } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMp3Player } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMug } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMugMarshmallows } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMugTea } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMugTeaSaucer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMushroom } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMusicAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMusicAltSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMusicMagnifyingGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMusicNote } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMusicNoteSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMusicSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMustache } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNarwhal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNestingDolls } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNfc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNfcLock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNfcMagnifyingGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNfcPen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNfcSignal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNfcSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNfcTrash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNigiri } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNose } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNote } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNoteMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNotebook } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNotes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectExclude } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectIntersect } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectSubtract } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectUnion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectsAlignBottom } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectsAlignCenterHorizontal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectsAlignCenterVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectsAlignLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectsAlignRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectsAlignTop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectsColumn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOctagon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOctagonCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOctagonDivide } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOctagonExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOctagonMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOctagonPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOctagonXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOctopus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOilCanDrip } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOilTemp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOilTemperature } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOlive } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOliveBranch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOmega } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOnion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOption } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOrnament } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOutlet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOven } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOverline } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPageBreak } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPageCaretDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPageCaretUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPaintBrushAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPaintbrushFine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPaintbrushPencil } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPaletteBoxes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPalletAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPalletBox } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPalletBoxes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPanFood } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPanFrying } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPancakes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPanelEws } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPanelFire } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPaperPlaneAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPaperPlaneTop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPaperclipVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faParagraphLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faParagraphRtl } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faParentheses } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faParenthesis } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faParkingCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faParkingCircleSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faParkingSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPartyBack } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPartyBell } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPartyHorn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPawAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPawClaws } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPawSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeach } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeanut } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeanuts } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeapod } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPear } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPedestal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPegasus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPenAltSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPenCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPenClipSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPenFancySlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPenField } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPenLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPenNibSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPenPaintbrush } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPenSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPenSwirl } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPencilMechanical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPencilPaintbrush } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPencilSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPennant } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeople } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeopleDress } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeopleDressSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeoplePants } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeoplePantsSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeopleSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPepper } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeriod } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonBikingMountain } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonCarry } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonCarryBox } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonDolly } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonDollyEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonDressFairy } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonDressSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonFairy } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonFromPortal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonPinball } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonRunningFast } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonSeat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonSeatReclined } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonSign } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonSkiJumping } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonSkiLift } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonSledding } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonSnowmobiling } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonToDoor } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonToPortal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneArrowDownLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneArrowRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneArrowUpRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneCircleAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneCircleDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneHangup } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneIncoming } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneIntercom } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneLaptop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneMissed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneOffice } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneOutgoing } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhonePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneRotary } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneSquareDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhotoFilmMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPi } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPiano } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPianoKeyboard } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPickaxe } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPickleball } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPie } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPig } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPinata } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPinball } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPineapple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPipe } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPipeCircleCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPipeCollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPipeSection } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPipeSmoking } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPipeValve } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPizza } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlaneAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlaneEngines } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlaneProp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlaneTail } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlaneUpSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlanetMoon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlanetRinged } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlateUtensils } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlayPause } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlusHexagon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlusLarge } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlusOctagon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPodium } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPodiumStar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPoliceBox } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPollPeople } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPompebled } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPool8Ball } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPopcorn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPopsicle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPortalEnter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPortalExit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPotFood } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPotato } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPrescriptionBottlePill } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPresentation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPresentationScreen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPretzel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPrintMagnifyingGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPrintSearch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPrintSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPro } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faProjector } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPump } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPumpkin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPuzzle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPuzzlePieceAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPuzzlePieceSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faQuestionSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faQuotes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRabbit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRabbitFast } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRabbitRunning } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRaccoon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRacquet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRadar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRadioAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRadioTuner } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRaindrops } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRam } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRampLoading } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRaygun } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleBarcode } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleCode } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleHd } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleHistory } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleHistoryCirclePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleHistoryCircleUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleLandscape } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectanglePortrait } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectanglePro } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleSd } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleTerminal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleVerticalHistory } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleWide } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectanglesMixed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faReel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faReflectBoth } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faReflectHorizontal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faReflectVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRefrigerator } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRepeat1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRepeat1Alt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRepeatAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faReplyClock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faReplyTime } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRestroomSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRetweetAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRhombus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRightFromLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRightLeftLarge } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRightLongToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRightToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRingDiamond } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRingsWedding } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRobotAstromech } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRocketLaunch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRollerCoaster } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRotateExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRotateReverse } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRouteHighway } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRouteInterstate } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRouter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRows } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRugbyBall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRulerTriangle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRv } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSack } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSalad } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSaltShaker } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSandwich } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSausage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSaveCircleArrowRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSaveCircleXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSaveTimes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSaxHot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSaxophone } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSaxophoneFire } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScalpel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScalpelLineDashed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScalpelPath } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScanner } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScannerGun } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScannerImage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScannerKeyboard } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScannerTouchscreen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScarecrow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScarf } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScreenUsers } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScreencast } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScreenshot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScribble } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScrollOld } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScrollRibbon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScrubber } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScythe } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSdCards } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSeal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSealExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSealQuestion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSeatAirline } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSemicolon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSend } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSendBack } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSendBackward } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSensor } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSensorAlert } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSensorCloud } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSensorFire } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSensorOn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSensorSmoke } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSensorTriangleExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShareAll } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSheep } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShelves } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShelvesEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShieldCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShieldCross } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShieldExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShieldKeyhole } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShieldMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShieldPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShieldQuartered } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShieldSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShieldTimes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShieldXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShippingTimed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShirtLongSleeve } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShirtRunning } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShirtTankTop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShishKebab } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShoppingBasketAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShortcake } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShovel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShovelSnow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShowerAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShowerDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShredder } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShutters } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShuttlecock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSickle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSidebar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSidebarFlip } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSigma } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignPost } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignPosts } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignPostsWrench } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignal1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignal2 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignal3 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignal4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalAlt1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalAlt2 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalAlt3 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalAlt4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalAltSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalBars } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalBarsFair } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalBarsGood } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalBarsSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalBarsStrong } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalBarsWeak } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalFair } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalGood } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalStream } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalStreamSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalStrong } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalWeak } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignatureLock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignatureSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSimCards } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSiren } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSirenOn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSkeleton } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSkeletonRibs } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSkiBoot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSkiBootSki } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSkiJump } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSkiLift } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSkullCow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSlashBack } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSlashForward } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSledding } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSlider } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSlidersHSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSlidersSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSlidersUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSlidersV } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSlidersVSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSlotMachine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSmilePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSmoke } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSnake } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSnooze } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSnowBlowing } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSnowflakeDroplets } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSnowflakes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSnowmanHead } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSnowmobile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSoftServe } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSolarSystem } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortCircleDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortCircleUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortShapesDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortShapesDownAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortShapesUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortShapesUpAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortSizeDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortSizeDownAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortSizeUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortSizeUpAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortUpDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSoup } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSpaceStationMoon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSpaceStationMoonAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSpaceStationMoonConstruction } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSpade } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSparkle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSparkles } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSpeaker } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSpeakers } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSpiderBlackWidow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSpiderWeb } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSpinnerScale } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSpinnerThird } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSplit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSportsball } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSprinkler } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSprinklerCeiling } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquare0 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquare1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquare2 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquare3 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquare4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquare5 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquare6 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquare7 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquare8 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquare9 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareA } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareALock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareAmpersand } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareArrowDownLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareArrowDownRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareArrowLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareArrowRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareArrowUpLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareB } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareC } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareChevronDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareChevronLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareChevronRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareChevronUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareCode } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareD } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareDashed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareDashedCirclePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareDivide } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareDownLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareDownRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareE } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareEllipsis } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareEllipsisVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareF } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareFragile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareG } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareI } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareInfo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareJ } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareK } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareKanban } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareL } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareList } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareM } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareN } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareO } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareP } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareParkingSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquarePhoneHangup } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareQ } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareQuarters } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareQuestion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareQuote } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareR } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareRing } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareRoot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareS } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareSliders } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareSlidersVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareSmall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareStar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareT } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareTerminal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareThisWayUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareU } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareUpLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareV } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareW } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareWineGlassCrack } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareX } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareY } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareZ } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquid } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquirrel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStaff } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStandardDefinition } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarChristmas } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarSharp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarSharpHalf } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarSharpHalfAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarSharpHalfStroke } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarShooting } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarfighter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarfighterAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarfighterAltAdvanced } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarfighterTwinIonEngine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarfighterTwinIonEngineAdvanced } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStars } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarship } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarshipFreighter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSteak } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSteeringWheel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStocking } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStomach } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStoreLock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStrawberry } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStretcher } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSubtitles } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSubtitlesSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSubwayTunnel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSunAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSunBright } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSunCloud } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSunDust } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSunHaze } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSunglasses } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSunrise } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSunset } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSushi } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSushiRoll } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSwap } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSwapArrows } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSword } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSwordLaser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSwordLaserAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSwords } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSwordsLaser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSymbols } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTRex } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTableCellsColumnUnlock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTableCellsLock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTableCellsUnlock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTableLayout } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTablePicnic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTablePivot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTableRows } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTableTree } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTabletAndroidAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTabletRugged } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTabletScreen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTachometerAltFastest } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTachometerAltSlow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTachometerAltSlowest } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTachometerFastest } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTachometerSlow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTachometerSlowest } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTaco } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTally } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTally1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTally2 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTally3 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTally4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTally5 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTamale } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTankWater } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTaxiBus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTeddyBear } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTelescope } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTeletypeAnswer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTemperatureFrigid } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTemperatureHot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTemperatureList } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTemperatureSnow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTemperatureSun } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTennisBall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTentDoublePeak } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faText } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTextSize } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTheta } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faThoughtBubble } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faThunderstormMoon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faThunderstormSun } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTick } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTicketAirline } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTicketPerforated } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTicketPerforatedPlane } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTicketPlane } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTickets } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTicketsAirline } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTicketsPerforated } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTicketsPerforatedPlane } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTicketsPlane } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTicketsSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTilde } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTimelineArrow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTimer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTimesHexagon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTimesOctagon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTimesToSlot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTire } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTireFlat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTirePressureWarning } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTireRugged } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToggleLargeOff } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToggleLargeOn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToiletPaperAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToiletPaperBlank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToiletPaperBlankUnder } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToiletPaperCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToiletPaperReverse } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToiletPaperReverseAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToiletPaperReverseSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToiletPaperUnder } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToiletPaperUnderSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToiletPaperXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTomato } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTombstone } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTombstoneAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTombstoneBlank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToothbrush } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTowerControl } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrafficCone } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrafficLightGo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrafficLightSlow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrafficLightStop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrainSubwayTunnel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrainTrack } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrainTunnel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTransformerBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTransporter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTransporter1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTransporter2 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTransporter3 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTransporter4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTransporter5 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTransporter6 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTransporter7 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTransporterEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashAltSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashArrowTurnLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashCanArrowTurnLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashCanCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashCanClock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashCanList } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashCanPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashCanSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashCanUndo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashCanXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashClock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashList } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashUndo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashUndoAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTreasureChest } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTreeAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTreeChristmas } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTreeDeciduous } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTreeDecorated } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTreeLarge } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTreePalm } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrees } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrianBalbot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTriangle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTriangleInstrument } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTriangleMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrianglePersonDigging } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTricycle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTricycleAdult } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrillium } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrophyAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrophyStar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckClock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckContainer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckContainerEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckCouch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckFire } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckFlatbed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckLadder } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckPlow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckRamp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckRampCouch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckTow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckUtensils } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrumpet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTtyAnswer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTugrikSign } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTurkey } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTurnDownLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTurnDownRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTurnLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTurnLeftDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTurnLeftUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTurnRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTurntable } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTurtle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTvMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTvRetro } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTypewriter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUfo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUfoBeam } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUmbrellaAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUmbrellaSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUnicorn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUniformMartialArts } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUnion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUpFromBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUpFromDottedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUpFromLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUpLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUpRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUpToBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUpToDottedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUpToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUsbDrive } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUsdCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUsdSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserAlien } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserBeardBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserBountyHunter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserChart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserChef } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserConstruction } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserCowboy } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserCrown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserDoctorHair } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserDoctorHairLong } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserDoctorMessage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserGroupCrown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserGroupSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserHair } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserHairBuns } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserHairLong } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserHairMullet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserHardHat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserHeadset } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserHelmetSafety } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserHoodie } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserMagnifyingGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserMdChat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserNurseHair } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserNurseHairLong } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserPilot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserPilotTie } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserPolice } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserPoliceTie } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserRobot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserRobotXmarks } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserShakespeare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserTieHair } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserTieHairLong } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserUnlock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserVisor } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserVneck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserVneckHair } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserVneckHairLong } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUsersClass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUsersCrown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUsersMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUtensilFork } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUtensilKnife } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUtensilsAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUtensilsSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUtilityPole } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUtilityPoleDouble } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVacuum } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVacuumRobot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faValueAbsolute } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVectorCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVectorPolygon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVentDamper } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVhs } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVideoArrowDownLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVideoArrowUpRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVideoCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVideoHandheld } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVideoPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faViolin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVolume } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVolumeMedium } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVolumeSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVoteNay } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaffle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWagonCovered } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWalker } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWallBrick } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWand } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWarehouseAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWarehouseFull } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWasher } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWashingMachine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWatch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWatchApple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWatchCalculator } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWatchFitness } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWatchSmart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaterArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaterArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaterLower } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaterRise } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWatermelonSlice } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWave } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWavePulse } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaveSine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaveTriangle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaveform } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaveformCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaveformLines } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaveformPath } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWavesSine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWebcam } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWebcamSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWebhook } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWhale } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWheat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWheatAwnSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWheatSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWhiskeyGlassIce } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWhistle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWifi1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWifi2 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWifiExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWifiFair } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWifiSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWifiWeak } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWindCircleExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWindTurbine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWindWarning } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWindow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWindowAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWindowFlip } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWindowFrame } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWindowFrameOpen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWindsock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWineGlassCrack } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWreath } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWreathLaurel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWrenchSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faXmarkHexagon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faXmarkLarge } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faXmarkOctagon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faXmarkToSlot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faZzz } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faActors, definition as faActorsBorderless, definition as faGb, definition as faLinear, definition as faProject, definition as faRegex, definition as faRivet, definition as faSelect, definition as faTs, definition as faVercel, definition as faWord } from "@fortawesome/free-solid-svg-icons/faSquare"; diff --git a/frontend/packages/icons/src/index.gen.ts b/frontend/packages/icons/src/index.gen.ts new file mode 100644 index 0000000000..97d5689fc0 --- /dev/null +++ b/frontend/packages/icons/src/index.gen.ts @@ -0,0 +1,4831 @@ +// This file is generated by scripts/postinstall.js +// Do not modify this file directly +// This file does not include pro icons, all pro icons are replaced with square icon. To use pro icons, please add FONTAWESOME_PACKAGE_TOKEN to your environment and rebuild this package. + +import { FontAwesomeIcon, FontAwesomeIconProps } from "@fortawesome/react-fontawesome"; +import { ComponentProps, createElement } from "react"; +export function Icon(props: Omit, 'icon'> & {icon: IconProp}) { return createElement(FontAwesomeIcon, props as FontAwesomeIconProps)} +export type IconProp = string | { prefix: string; iconName: string } | [string, string]; +export { definition as fa2 } from "@fortawesome/free-solid-svg-icons/fa2"; +export { definition as fa3 } from "@fortawesome/free-solid-svg-icons/fa3"; +export { definition as fa4 } from "@fortawesome/free-solid-svg-icons/fa4"; +export { definition as fa5 } from "@fortawesome/free-solid-svg-icons/fa5"; +export { definition as fa6 } from "@fortawesome/free-solid-svg-icons/fa6"; +export { definition as fa7 } from "@fortawesome/free-solid-svg-icons/fa7"; +export { definition as fa8 } from "@fortawesome/free-solid-svg-icons/fa8"; +export { definition as fa9 } from "@fortawesome/free-solid-svg-icons/fa9"; +export { definition as faA } from "@fortawesome/free-solid-svg-icons/faA"; +export { definition as faAd } from "@fortawesome/free-solid-svg-icons/faAd"; +export { definition as faAdd } from "@fortawesome/free-solid-svg-icons/faAdd"; +export { definition as faAddressBook } from "@fortawesome/free-solid-svg-icons/faAddressBook"; +export { definition as faAddressCard } from "@fortawesome/free-solid-svg-icons/faAddressCard"; +export { definition as faAdjust } from "@fortawesome/free-solid-svg-icons/faAdjust"; +export { definition as faAirFreshener } from "@fortawesome/free-solid-svg-icons/faAirFreshener"; +export { definition as faAlignCenter } from "@fortawesome/free-solid-svg-icons/faAlignCenter"; +export { definition as faAlignJustify } from "@fortawesome/free-solid-svg-icons/faAlignJustify"; +export { definition as faAlignLeft } from "@fortawesome/free-solid-svg-icons/faAlignLeft"; +export { definition as faAlignRight } from "@fortawesome/free-solid-svg-icons/faAlignRight"; +export { definition as faAllergies } from "@fortawesome/free-solid-svg-icons/faAllergies"; +export { definition as faAmbulance } from "@fortawesome/free-solid-svg-icons/faAmbulance"; +export { definition as faAmericanSignLanguageInterpreting } from "@fortawesome/free-solid-svg-icons/faAmericanSignLanguageInterpreting"; +export { definition as faAnchor } from "@fortawesome/free-solid-svg-icons/faAnchor"; +export { definition as faAnchorCircleCheck } from "@fortawesome/free-solid-svg-icons/faAnchorCircleCheck"; +export { definition as faAnchorCircleExclamation } from "@fortawesome/free-solid-svg-icons/faAnchorCircleExclamation"; +export { definition as faAnchorCircleXmark } from "@fortawesome/free-solid-svg-icons/faAnchorCircleXmark"; +export { definition as faAnchorLock } from "@fortawesome/free-solid-svg-icons/faAnchorLock"; +export { definition as faAngleDoubleDown } from "@fortawesome/free-solid-svg-icons/faAngleDoubleDown"; +export { definition as faAngleDoubleLeft } from "@fortawesome/free-solid-svg-icons/faAngleDoubleLeft"; +export { definition as faAngleDoubleRight } from "@fortawesome/free-solid-svg-icons/faAngleDoubleRight"; +export { definition as faAngleDoubleUp } from "@fortawesome/free-solid-svg-icons/faAngleDoubleUp"; +export { definition as faAngleDown } from "@fortawesome/free-solid-svg-icons/faAngleDown"; +export { definition as faAngleLeft } from "@fortawesome/free-solid-svg-icons/faAngleLeft"; +export { definition as faAngleRight } from "@fortawesome/free-solid-svg-icons/faAngleRight"; +export { definition as faAngleUp } from "@fortawesome/free-solid-svg-icons/faAngleUp"; +export { definition as faAnglesDown } from "@fortawesome/free-solid-svg-icons/faAnglesDown"; +export { definition as faAnglesLeft } from "@fortawesome/free-solid-svg-icons/faAnglesLeft"; +export { definition as faAnglesRight } from "@fortawesome/free-solid-svg-icons/faAnglesRight"; +export { definition as faAnglesUp } from "@fortawesome/free-solid-svg-icons/faAnglesUp"; +export { definition as faAngry } from "@fortawesome/free-solid-svg-icons/faAngry"; +export { definition as faAnkh } from "@fortawesome/free-solid-svg-icons/faAnkh"; +export { definition as faAppleAlt } from "@fortawesome/free-solid-svg-icons/faAppleAlt"; +export { definition as faAppleWhole } from "@fortawesome/free-solid-svg-icons/faAppleWhole"; +export { definition as faArchive } from "@fortawesome/free-solid-svg-icons/faArchive"; +export { definition as faArchway } from "@fortawesome/free-solid-svg-icons/faArchway"; +export { definition as faAreaChart } from "@fortawesome/free-solid-svg-icons/faAreaChart"; +export { definition as faArrowAltCircleDown } from "@fortawesome/free-solid-svg-icons/faArrowAltCircleDown"; +export { definition as faArrowAltCircleLeft } from "@fortawesome/free-solid-svg-icons/faArrowAltCircleLeft"; +export { definition as faArrowAltCircleRight } from "@fortawesome/free-solid-svg-icons/faArrowAltCircleRight"; +export { definition as faArrowAltCircleUp } from "@fortawesome/free-solid-svg-icons/faArrowAltCircleUp"; +export { definition as faArrowCircleDown } from "@fortawesome/free-solid-svg-icons/faArrowCircleDown"; +export { definition as faArrowCircleLeft } from "@fortawesome/free-solid-svg-icons/faArrowCircleLeft"; +export { definition as faArrowCircleRight } from "@fortawesome/free-solid-svg-icons/faArrowCircleRight"; +export { definition as faArrowCircleUp } from "@fortawesome/free-solid-svg-icons/faArrowCircleUp"; +export { definition as faArrowDown } from "@fortawesome/free-solid-svg-icons/faArrowDown"; +export { definition as faArrowDown19 } from "@fortawesome/free-solid-svg-icons/faArrowDown19"; +export { definition as faArrowDown91 } from "@fortawesome/free-solid-svg-icons/faArrowDown91"; +export { definition as faArrowDownAZ } from "@fortawesome/free-solid-svg-icons/faArrowDownAZ"; +export { definition as faArrowDownLong } from "@fortawesome/free-solid-svg-icons/faArrowDownLong"; +export { definition as faArrowDownShortWide } from "@fortawesome/free-solid-svg-icons/faArrowDownShortWide"; +export { definition as faArrowDownUpAcrossLine } from "@fortawesome/free-solid-svg-icons/faArrowDownUpAcrossLine"; +export { definition as faArrowDownUpLock } from "@fortawesome/free-solid-svg-icons/faArrowDownUpLock"; +export { definition as faArrowDownWideShort } from "@fortawesome/free-solid-svg-icons/faArrowDownWideShort"; +export { definition as faArrowDownZA } from "@fortawesome/free-solid-svg-icons/faArrowDownZA"; +export { definition as faArrowLeft } from "@fortawesome/free-solid-svg-icons/faArrowLeft"; +export { definition as faArrowLeftLong } from "@fortawesome/free-solid-svg-icons/faArrowLeftLong"; +export { definition as faArrowLeftRotate } from "@fortawesome/free-solid-svg-icons/faArrowLeftRotate"; +export { definition as faArrowPointer } from "@fortawesome/free-solid-svg-icons/faArrowPointer"; +export { definition as faArrowRight } from "@fortawesome/free-solid-svg-icons/faArrowRight"; +export { definition as faArrowRightArrowLeft } from "@fortawesome/free-solid-svg-icons/faArrowRightArrowLeft"; +export { definition as faArrowRightFromBracket } from "@fortawesome/free-solid-svg-icons/faArrowRightFromBracket"; +export { definition as faArrowRightFromFile } from "@fortawesome/free-solid-svg-icons/faArrowRightFromFile"; +export { definition as faArrowRightLong } from "@fortawesome/free-solid-svg-icons/faArrowRightLong"; +export { definition as faArrowRightRotate } from "@fortawesome/free-solid-svg-icons/faArrowRightRotate"; +export { definition as faArrowRightToBracket } from "@fortawesome/free-solid-svg-icons/faArrowRightToBracket"; +export { definition as faArrowRightToCity } from "@fortawesome/free-solid-svg-icons/faArrowRightToCity"; +export { definition as faArrowRightToFile } from "@fortawesome/free-solid-svg-icons/faArrowRightToFile"; +export { definition as faArrowRotateBack } from "@fortawesome/free-solid-svg-icons/faArrowRotateBack"; +export { definition as faArrowRotateBackward } from "@fortawesome/free-solid-svg-icons/faArrowRotateBackward"; +export { definition as faArrowRotateForward } from "@fortawesome/free-solid-svg-icons/faArrowRotateForward"; +export { definition as faArrowRotateLeft } from "@fortawesome/free-solid-svg-icons/faArrowRotateLeft"; +export { definition as faArrowRotateRight } from "@fortawesome/free-solid-svg-icons/faArrowRotateRight"; +export { definition as faArrowTrendDown } from "@fortawesome/free-solid-svg-icons/faArrowTrendDown"; +export { definition as faArrowTrendUp } from "@fortawesome/free-solid-svg-icons/faArrowTrendUp"; +export { definition as faArrowTurnDown } from "@fortawesome/free-solid-svg-icons/faArrowTurnDown"; +export { definition as faArrowTurnUp } from "@fortawesome/free-solid-svg-icons/faArrowTurnUp"; +export { definition as faArrowUp } from "@fortawesome/free-solid-svg-icons/faArrowUp"; +export { definition as faArrowUp19 } from "@fortawesome/free-solid-svg-icons/faArrowUp19"; +export { definition as faArrowUp91 } from "@fortawesome/free-solid-svg-icons/faArrowUp91"; +export { definition as faArrowUpAZ } from "@fortawesome/free-solid-svg-icons/faArrowUpAZ"; +export { definition as faArrowUpFromBracket } from "@fortawesome/free-solid-svg-icons/faArrowUpFromBracket"; +export { definition as faArrowUpFromGroundWater } from "@fortawesome/free-solid-svg-icons/faArrowUpFromGroundWater"; +export { definition as faArrowUpFromWaterPump } from "@fortawesome/free-solid-svg-icons/faArrowUpFromWaterPump"; +export { definition as faArrowUpLong } from "@fortawesome/free-solid-svg-icons/faArrowUpLong"; +export { definition as faArrowUpRightDots } from "@fortawesome/free-solid-svg-icons/faArrowUpRightDots"; +export { definition as faArrowUpRightFromSquare } from "@fortawesome/free-solid-svg-icons/faArrowUpRightFromSquare"; +export { definition as faArrowUpShortWide } from "@fortawesome/free-solid-svg-icons/faArrowUpShortWide"; +export { definition as faArrowUpWideShort } from "@fortawesome/free-solid-svg-icons/faArrowUpWideShort"; +export { definition as faArrowUpZA } from "@fortawesome/free-solid-svg-icons/faArrowUpZA"; +export { definition as faArrows } from "@fortawesome/free-solid-svg-icons/faArrows"; +export { definition as faArrowsAlt } from "@fortawesome/free-solid-svg-icons/faArrowsAlt"; +export { definition as faArrowsAltH } from "@fortawesome/free-solid-svg-icons/faArrowsAltH"; +export { definition as faArrowsAltV } from "@fortawesome/free-solid-svg-icons/faArrowsAltV"; +export { definition as faArrowsDownToLine } from "@fortawesome/free-solid-svg-icons/faArrowsDownToLine"; +export { definition as faArrowsDownToPeople } from "@fortawesome/free-solid-svg-icons/faArrowsDownToPeople"; +export { definition as faArrowsH } from "@fortawesome/free-solid-svg-icons/faArrowsH"; +export { definition as faArrowsLeftRight } from "@fortawesome/free-solid-svg-icons/faArrowsLeftRight"; +export { definition as faArrowsLeftRightToLine } from "@fortawesome/free-solid-svg-icons/faArrowsLeftRightToLine"; +export { definition as faArrowsRotate } from "@fortawesome/free-solid-svg-icons/faArrowsRotate"; +export { definition as faArrowsSpin } from "@fortawesome/free-solid-svg-icons/faArrowsSpin"; +export { definition as faArrowsSplitUpAndLeft } from "@fortawesome/free-solid-svg-icons/faArrowsSplitUpAndLeft"; +export { definition as faArrowsToCircle } from "@fortawesome/free-solid-svg-icons/faArrowsToCircle"; +export { definition as faArrowsToDot } from "@fortawesome/free-solid-svg-icons/faArrowsToDot"; +export { definition as faArrowsToEye } from "@fortawesome/free-solid-svg-icons/faArrowsToEye"; +export { definition as faArrowsTurnRight } from "@fortawesome/free-solid-svg-icons/faArrowsTurnRight"; +export { definition as faArrowsTurnToDots } from "@fortawesome/free-solid-svg-icons/faArrowsTurnToDots"; +export { definition as faArrowsUpDown } from "@fortawesome/free-solid-svg-icons/faArrowsUpDown"; +export { definition as faArrowsUpDownLeftRight } from "@fortawesome/free-solid-svg-icons/faArrowsUpDownLeftRight"; +export { definition as faArrowsUpToLine } from "@fortawesome/free-solid-svg-icons/faArrowsUpToLine"; +export { definition as faArrowsV } from "@fortawesome/free-solid-svg-icons/faArrowsV"; +export { definition as faAslInterpreting } from "@fortawesome/free-solid-svg-icons/faAslInterpreting"; +export { definition as faAssistiveListeningSystems } from "@fortawesome/free-solid-svg-icons/faAssistiveListeningSystems"; +export { definition as faAsterisk } from "@fortawesome/free-solid-svg-icons/faAsterisk"; +export { definition as faAt } from "@fortawesome/free-solid-svg-icons/faAt"; +export { definition as faAtlas } from "@fortawesome/free-solid-svg-icons/faAtlas"; +export { definition as faAtom } from "@fortawesome/free-solid-svg-icons/faAtom"; +export { definition as faAudioDescription } from "@fortawesome/free-solid-svg-icons/faAudioDescription"; +export { definition as faAustralSign } from "@fortawesome/free-solid-svg-icons/faAustralSign"; +export { definition as faAutomobile } from "@fortawesome/free-solid-svg-icons/faAutomobile"; +export { definition as faAward } from "@fortawesome/free-solid-svg-icons/faAward"; +export { definition as faB } from "@fortawesome/free-solid-svg-icons/faB"; +export { definition as faBaby } from "@fortawesome/free-solid-svg-icons/faBaby"; +export { definition as faBabyCarriage } from "@fortawesome/free-solid-svg-icons/faBabyCarriage"; +export { definition as faBackspace } from "@fortawesome/free-solid-svg-icons/faBackspace"; +export { definition as faBackward } from "@fortawesome/free-solid-svg-icons/faBackward"; +export { definition as faBackwardFast } from "@fortawesome/free-solid-svg-icons/faBackwardFast"; +export { definition as faBackwardStep } from "@fortawesome/free-solid-svg-icons/faBackwardStep"; +export { definition as faBacon } from "@fortawesome/free-solid-svg-icons/faBacon"; +export { definition as faBacteria } from "@fortawesome/free-solid-svg-icons/faBacteria"; +export { definition as faBacterium } from "@fortawesome/free-solid-svg-icons/faBacterium"; +export { definition as faBagShopping } from "@fortawesome/free-solid-svg-icons/faBagShopping"; +export { definition as faBahai } from "@fortawesome/free-solid-svg-icons/faBahai"; +export { definition as faBahtSign } from "@fortawesome/free-solid-svg-icons/faBahtSign"; +export { definition as faBalanceScale } from "@fortawesome/free-solid-svg-icons/faBalanceScale"; +export { definition as faBalanceScaleLeft } from "@fortawesome/free-solid-svg-icons/faBalanceScaleLeft"; +export { definition as faBalanceScaleRight } from "@fortawesome/free-solid-svg-icons/faBalanceScaleRight"; +export { definition as faBan } from "@fortawesome/free-solid-svg-icons/faBan"; +export { definition as faBanSmoking } from "@fortawesome/free-solid-svg-icons/faBanSmoking"; +export { definition as faBandAid } from "@fortawesome/free-solid-svg-icons/faBandAid"; +export { definition as faBandage } from "@fortawesome/free-solid-svg-icons/faBandage"; +export { definition as faBangladeshiTakaSign } from "@fortawesome/free-solid-svg-icons/faBangladeshiTakaSign"; +export { definition as faBank } from "@fortawesome/free-solid-svg-icons/faBank"; +export { definition as faBarChart } from "@fortawesome/free-solid-svg-icons/faBarChart"; +export { definition as faBarcode } from "@fortawesome/free-solid-svg-icons/faBarcode"; +export { definition as faBars } from "@fortawesome/free-solid-svg-icons/faBars"; +export { definition as faBarsProgress } from "@fortawesome/free-solid-svg-icons/faBarsProgress"; +export { definition as faBarsStaggered } from "@fortawesome/free-solid-svg-icons/faBarsStaggered"; +export { definition as faBaseball } from "@fortawesome/free-solid-svg-icons/faBaseball"; +export { definition as faBaseballBall } from "@fortawesome/free-solid-svg-icons/faBaseballBall"; +export { definition as faBaseballBatBall } from "@fortawesome/free-solid-svg-icons/faBaseballBatBall"; +export { definition as faBasketShopping } from "@fortawesome/free-solid-svg-icons/faBasketShopping"; +export { definition as faBasketball } from "@fortawesome/free-solid-svg-icons/faBasketball"; +export { definition as faBasketballBall } from "@fortawesome/free-solid-svg-icons/faBasketballBall"; +export { definition as faBath } from "@fortawesome/free-solid-svg-icons/faBath"; +export { definition as faBathtub } from "@fortawesome/free-solid-svg-icons/faBathtub"; +export { definition as faBattery } from "@fortawesome/free-solid-svg-icons/faBattery"; +export { definition as faBattery0 } from "@fortawesome/free-solid-svg-icons/faBattery0"; +export { definition as faBattery2 } from "@fortawesome/free-solid-svg-icons/faBattery2"; +export { definition as faBattery3 } from "@fortawesome/free-solid-svg-icons/faBattery3"; +export { definition as faBattery4 } from "@fortawesome/free-solid-svg-icons/faBattery4"; +export { definition as faBattery5 } from "@fortawesome/free-solid-svg-icons/faBattery5"; +export { definition as faBatteryCar } from "@fortawesome/free-solid-svg-icons/faBatteryCar"; +export { definition as faBatteryEmpty } from "@fortawesome/free-solid-svg-icons/faBatteryEmpty"; +export { definition as faBatteryFull } from "@fortawesome/free-solid-svg-icons/faBatteryFull"; +export { definition as faBatteryHalf } from "@fortawesome/free-solid-svg-icons/faBatteryHalf"; +export { definition as faBatteryQuarter } from "@fortawesome/free-solid-svg-icons/faBatteryQuarter"; +export { definition as faBatteryThreeQuarters } from "@fortawesome/free-solid-svg-icons/faBatteryThreeQuarters"; +export { definition as faBed } from "@fortawesome/free-solid-svg-icons/faBed"; +export { definition as faBedPulse } from "@fortawesome/free-solid-svg-icons/faBedPulse"; +export { definition as faBeer } from "@fortawesome/free-solid-svg-icons/faBeer"; +export { definition as faBeerMugEmpty } from "@fortawesome/free-solid-svg-icons/faBeerMugEmpty"; +export { definition as faBell } from "@fortawesome/free-solid-svg-icons/faBell"; +export { definition as faBellConcierge } from "@fortawesome/free-solid-svg-icons/faBellConcierge"; +export { definition as faBellSlash } from "@fortawesome/free-solid-svg-icons/faBellSlash"; +export { definition as faBezierCurve } from "@fortawesome/free-solid-svg-icons/faBezierCurve"; +export { definition as faBible } from "@fortawesome/free-solid-svg-icons/faBible"; +export { definition as faBicycle } from "@fortawesome/free-solid-svg-icons/faBicycle"; +export { definition as faBiking } from "@fortawesome/free-solid-svg-icons/faBiking"; +export { definition as faBinoculars } from "@fortawesome/free-solid-svg-icons/faBinoculars"; +export { definition as faBiohazard } from "@fortawesome/free-solid-svg-icons/faBiohazard"; +export { definition as faBirthdayCake } from "@fortawesome/free-solid-svg-icons/faBirthdayCake"; +export { definition as faBitcoinSign } from "@fortawesome/free-solid-svg-icons/faBitcoinSign"; +export { definition as faBlackboard } from "@fortawesome/free-solid-svg-icons/faBlackboard"; +export { definition as faBlender } from "@fortawesome/free-solid-svg-icons/faBlender"; +export { definition as faBlenderPhone } from "@fortawesome/free-solid-svg-icons/faBlenderPhone"; +export { definition as faBlind } from "@fortawesome/free-solid-svg-icons/faBlind"; +export { definition as faBlog } from "@fortawesome/free-solid-svg-icons/faBlog"; +export { definition as faBold } from "@fortawesome/free-solid-svg-icons/faBold"; +export { definition as faBolt } from "@fortawesome/free-solid-svg-icons/faBolt"; +export { definition as faBoltLightning } from "@fortawesome/free-solid-svg-icons/faBoltLightning"; +export { definition as faBomb } from "@fortawesome/free-solid-svg-icons/faBomb"; +export { definition as faBone } from "@fortawesome/free-solid-svg-icons/faBone"; +export { definition as faBong } from "@fortawesome/free-solid-svg-icons/faBong"; +export { definition as faBook } from "@fortawesome/free-solid-svg-icons/faBook"; +export { definition as faBookAtlas } from "@fortawesome/free-solid-svg-icons/faBookAtlas"; +export { definition as faBookBible } from "@fortawesome/free-solid-svg-icons/faBookBible"; +export { definition as faBookBookmark } from "@fortawesome/free-solid-svg-icons/faBookBookmark"; +export { definition as faBookDead } from "@fortawesome/free-solid-svg-icons/faBookDead"; +export { definition as faBookJournalWhills } from "@fortawesome/free-solid-svg-icons/faBookJournalWhills"; +export { definition as faBookMedical } from "@fortawesome/free-solid-svg-icons/faBookMedical"; +export { definition as faBookOpen } from "@fortawesome/free-solid-svg-icons/faBookOpen"; +export { definition as faBookOpenReader } from "@fortawesome/free-solid-svg-icons/faBookOpenReader"; +export { definition as faBookQuran } from "@fortawesome/free-solid-svg-icons/faBookQuran"; +export { definition as faBookReader } from "@fortawesome/free-solid-svg-icons/faBookReader"; +export { definition as faBookSkull } from "@fortawesome/free-solid-svg-icons/faBookSkull"; +export { definition as faBookTanakh } from "@fortawesome/free-solid-svg-icons/faBookTanakh"; +export { definition as faBookmark } from "@fortawesome/free-solid-svg-icons/faBookmark"; +export { definition as faBorderAll } from "@fortawesome/free-solid-svg-icons/faBorderAll"; +export { definition as faBorderNone } from "@fortawesome/free-solid-svg-icons/faBorderNone"; +export { definition as faBorderStyle } from "@fortawesome/free-solid-svg-icons/faBorderStyle"; +export { definition as faBorderTopLeft } from "@fortawesome/free-solid-svg-icons/faBorderTopLeft"; +export { definition as faBoreHole } from "@fortawesome/free-solid-svg-icons/faBoreHole"; +export { definition as faBottleDroplet } from "@fortawesome/free-solid-svg-icons/faBottleDroplet"; +export { definition as faBottleWater } from "@fortawesome/free-solid-svg-icons/faBottleWater"; +export { definition as faBowlFood } from "@fortawesome/free-solid-svg-icons/faBowlFood"; +export { definition as faBowlRice } from "@fortawesome/free-solid-svg-icons/faBowlRice"; +export { definition as faBowlingBall } from "@fortawesome/free-solid-svg-icons/faBowlingBall"; +export { definition as faBox } from "@fortawesome/free-solid-svg-icons/faBox"; +export { definition as faBoxArchive } from "@fortawesome/free-solid-svg-icons/faBoxArchive"; +export { definition as faBoxOpen } from "@fortawesome/free-solid-svg-icons/faBoxOpen"; +export { definition as faBoxTissue } from "@fortawesome/free-solid-svg-icons/faBoxTissue"; +export { definition as faBoxes } from "@fortawesome/free-solid-svg-icons/faBoxes"; +export { definition as faBoxesAlt } from "@fortawesome/free-solid-svg-icons/faBoxesAlt"; +export { definition as faBoxesPacking } from "@fortawesome/free-solid-svg-icons/faBoxesPacking"; +export { definition as faBoxesStacked } from "@fortawesome/free-solid-svg-icons/faBoxesStacked"; +export { definition as faBraille } from "@fortawesome/free-solid-svg-icons/faBraille"; +export { definition as faBrain } from "@fortawesome/free-solid-svg-icons/faBrain"; +export { definition as faBrazilianRealSign } from "@fortawesome/free-solid-svg-icons/faBrazilianRealSign"; +export { definition as faBreadSlice } from "@fortawesome/free-solid-svg-icons/faBreadSlice"; +export { definition as faBridge } from "@fortawesome/free-solid-svg-icons/faBridge"; +export { definition as faBridgeCircleCheck } from "@fortawesome/free-solid-svg-icons/faBridgeCircleCheck"; +export { definition as faBridgeCircleExclamation } from "@fortawesome/free-solid-svg-icons/faBridgeCircleExclamation"; +export { definition as faBridgeCircleXmark } from "@fortawesome/free-solid-svg-icons/faBridgeCircleXmark"; +export { definition as faBridgeLock } from "@fortawesome/free-solid-svg-icons/faBridgeLock"; +export { definition as faBridgeWater } from "@fortawesome/free-solid-svg-icons/faBridgeWater"; +export { definition as faBriefcase } from "@fortawesome/free-solid-svg-icons/faBriefcase"; +export { definition as faBriefcaseClock } from "@fortawesome/free-solid-svg-icons/faBriefcaseClock"; +export { definition as faBriefcaseMedical } from "@fortawesome/free-solid-svg-icons/faBriefcaseMedical"; +export { definition as faBroadcastTower } from "@fortawesome/free-solid-svg-icons/faBroadcastTower"; +export { definition as faBroom } from "@fortawesome/free-solid-svg-icons/faBroom"; +export { definition as faBroomBall } from "@fortawesome/free-solid-svg-icons/faBroomBall"; +export { definition as faBrush } from "@fortawesome/free-solid-svg-icons/faBrush"; +export { definition as faBucket } from "@fortawesome/free-solid-svg-icons/faBucket"; +export { definition as faBug } from "@fortawesome/free-solid-svg-icons/faBug"; +export { definition as faBugSlash } from "@fortawesome/free-solid-svg-icons/faBugSlash"; +export { definition as faBugs } from "@fortawesome/free-solid-svg-icons/faBugs"; +export { definition as faBuilding } from "@fortawesome/free-solid-svg-icons/faBuilding"; +export { definition as faBuildingCircleArrowRight } from "@fortawesome/free-solid-svg-icons/faBuildingCircleArrowRight"; +export { definition as faBuildingCircleCheck } from "@fortawesome/free-solid-svg-icons/faBuildingCircleCheck"; +export { definition as faBuildingCircleExclamation } from "@fortawesome/free-solid-svg-icons/faBuildingCircleExclamation"; +export { definition as faBuildingCircleXmark } from "@fortawesome/free-solid-svg-icons/faBuildingCircleXmark"; +export { definition as faBuildingColumns } from "@fortawesome/free-solid-svg-icons/faBuildingColumns"; +export { definition as faBuildingFlag } from "@fortawesome/free-solid-svg-icons/faBuildingFlag"; +export { definition as faBuildingLock } from "@fortawesome/free-solid-svg-icons/faBuildingLock"; +export { definition as faBuildingNgo } from "@fortawesome/free-solid-svg-icons/faBuildingNgo"; +export { definition as faBuildingShield } from "@fortawesome/free-solid-svg-icons/faBuildingShield"; +export { definition as faBuildingUn } from "@fortawesome/free-solid-svg-icons/faBuildingUn"; +export { definition as faBuildingUser } from "@fortawesome/free-solid-svg-icons/faBuildingUser"; +export { definition as faBuildingWheat } from "@fortawesome/free-solid-svg-icons/faBuildingWheat"; +export { definition as faBullhorn } from "@fortawesome/free-solid-svg-icons/faBullhorn"; +export { definition as faBullseye } from "@fortawesome/free-solid-svg-icons/faBullseye"; +export { definition as faBurger } from "@fortawesome/free-solid-svg-icons/faBurger"; +export { definition as faBurn } from "@fortawesome/free-solid-svg-icons/faBurn"; +export { definition as faBurst } from "@fortawesome/free-solid-svg-icons/faBurst"; +export { definition as faBus } from "@fortawesome/free-solid-svg-icons/faBus"; +export { definition as faBusAlt } from "@fortawesome/free-solid-svg-icons/faBusAlt"; +export { definition as faBusSimple } from "@fortawesome/free-solid-svg-icons/faBusSimple"; +export { definition as faBusinessTime } from "@fortawesome/free-solid-svg-icons/faBusinessTime"; +export { definition as faC } from "@fortawesome/free-solid-svg-icons/faC"; +export { definition as faCab } from "@fortawesome/free-solid-svg-icons/faCab"; +export { definition as faCableCar } from "@fortawesome/free-solid-svg-icons/faCableCar"; +export { definition as faCake } from "@fortawesome/free-solid-svg-icons/faCake"; +export { definition as faCakeCandles } from "@fortawesome/free-solid-svg-icons/faCakeCandles"; +export { definition as faCalculator } from "@fortawesome/free-solid-svg-icons/faCalculator"; +export { definition as faCalendar } from "@fortawesome/free-solid-svg-icons/faCalendar"; +export { definition as faCalendarAlt } from "@fortawesome/free-solid-svg-icons/faCalendarAlt"; +export { definition as faCalendarCheck } from "@fortawesome/free-solid-svg-icons/faCalendarCheck"; +export { definition as faCalendarDay } from "@fortawesome/free-solid-svg-icons/faCalendarDay"; +export { definition as faCalendarDays } from "@fortawesome/free-solid-svg-icons/faCalendarDays"; +export { definition as faCalendarMinus } from "@fortawesome/free-solid-svg-icons/faCalendarMinus"; +export { definition as faCalendarPlus } from "@fortawesome/free-solid-svg-icons/faCalendarPlus"; +export { definition as faCalendarTimes } from "@fortawesome/free-solid-svg-icons/faCalendarTimes"; +export { definition as faCalendarWeek } from "@fortawesome/free-solid-svg-icons/faCalendarWeek"; +export { definition as faCalendarXmark } from "@fortawesome/free-solid-svg-icons/faCalendarXmark"; +export { definition as faCamera } from "@fortawesome/free-solid-svg-icons/faCamera"; +export { definition as faCameraAlt } from "@fortawesome/free-solid-svg-icons/faCameraAlt"; +export { definition as faCameraRetro } from "@fortawesome/free-solid-svg-icons/faCameraRetro"; +export { definition as faCameraRotate } from "@fortawesome/free-solid-svg-icons/faCameraRotate"; +export { definition as faCampground } from "@fortawesome/free-solid-svg-icons/faCampground"; +export { definition as faCancel } from "@fortawesome/free-solid-svg-icons/faCancel"; +export { definition as faCandyCane } from "@fortawesome/free-solid-svg-icons/faCandyCane"; +export { definition as faCannabis } from "@fortawesome/free-solid-svg-icons/faCannabis"; +export { definition as faCapsules } from "@fortawesome/free-solid-svg-icons/faCapsules"; +export { definition as faCar } from "@fortawesome/free-solid-svg-icons/faCar"; +export { definition as faCarAlt } from "@fortawesome/free-solid-svg-icons/faCarAlt"; +export { definition as faCarBattery } from "@fortawesome/free-solid-svg-icons/faCarBattery"; +export { definition as faCarBurst } from "@fortawesome/free-solid-svg-icons/faCarBurst"; +export { definition as faCarCrash } from "@fortawesome/free-solid-svg-icons/faCarCrash"; +export { definition as faCarOn } from "@fortawesome/free-solid-svg-icons/faCarOn"; +export { definition as faCarRear } from "@fortawesome/free-solid-svg-icons/faCarRear"; +export { definition as faCarSide } from "@fortawesome/free-solid-svg-icons/faCarSide"; +export { definition as faCarTunnel } from "@fortawesome/free-solid-svg-icons/faCarTunnel"; +export { definition as faCaravan } from "@fortawesome/free-solid-svg-icons/faCaravan"; +export { definition as faCaretDown } from "@fortawesome/free-solid-svg-icons/faCaretDown"; +export { definition as faCaretLeft } from "@fortawesome/free-solid-svg-icons/faCaretLeft"; +export { definition as faCaretRight } from "@fortawesome/free-solid-svg-icons/faCaretRight"; +export { definition as faCaretSquareDown } from "@fortawesome/free-solid-svg-icons/faCaretSquareDown"; +export { definition as faCaretSquareLeft } from "@fortawesome/free-solid-svg-icons/faCaretSquareLeft"; +export { definition as faCaretSquareRight } from "@fortawesome/free-solid-svg-icons/faCaretSquareRight"; +export { definition as faCaretSquareUp } from "@fortawesome/free-solid-svg-icons/faCaretSquareUp"; +export { definition as faCaretUp } from "@fortawesome/free-solid-svg-icons/faCaretUp"; +export { definition as faCarriageBaby } from "@fortawesome/free-solid-svg-icons/faCarriageBaby"; +export { definition as faCarrot } from "@fortawesome/free-solid-svg-icons/faCarrot"; +export { definition as faCartArrowDown } from "@fortawesome/free-solid-svg-icons/faCartArrowDown"; +export { definition as faCartFlatbed } from "@fortawesome/free-solid-svg-icons/faCartFlatbed"; +export { definition as faCartFlatbedSuitcase } from "@fortawesome/free-solid-svg-icons/faCartFlatbedSuitcase"; +export { definition as faCartPlus } from "@fortawesome/free-solid-svg-icons/faCartPlus"; +export { definition as faCartShopping } from "@fortawesome/free-solid-svg-icons/faCartShopping"; +export { definition as faCashRegister } from "@fortawesome/free-solid-svg-icons/faCashRegister"; +export { definition as faCat } from "@fortawesome/free-solid-svg-icons/faCat"; +export { definition as faCediSign } from "@fortawesome/free-solid-svg-icons/faCediSign"; +export { definition as faCentSign } from "@fortawesome/free-solid-svg-icons/faCentSign"; +export { definition as faCertificate } from "@fortawesome/free-solid-svg-icons/faCertificate"; +export { definition as faChain } from "@fortawesome/free-solid-svg-icons/faChain"; +export { definition as faChainBroken } from "@fortawesome/free-solid-svg-icons/faChainBroken"; +export { definition as faChainSlash } from "@fortawesome/free-solid-svg-icons/faChainSlash"; +export { definition as faChair } from "@fortawesome/free-solid-svg-icons/faChair"; +export { definition as faChalkboard } from "@fortawesome/free-solid-svg-icons/faChalkboard"; +export { definition as faChalkboardTeacher } from "@fortawesome/free-solid-svg-icons/faChalkboardTeacher"; +export { definition as faChalkboardUser } from "@fortawesome/free-solid-svg-icons/faChalkboardUser"; +export { definition as faChampagneGlasses } from "@fortawesome/free-solid-svg-icons/faChampagneGlasses"; +export { definition as faChargingStation } from "@fortawesome/free-solid-svg-icons/faChargingStation"; +export { definition as faChartArea } from "@fortawesome/free-solid-svg-icons/faChartArea"; +export { definition as faChartBar } from "@fortawesome/free-solid-svg-icons/faChartBar"; +export { definition as faChartColumn } from "@fortawesome/free-solid-svg-icons/faChartColumn"; +export { definition as faChartDiagram } from "@fortawesome/free-solid-svg-icons/faChartDiagram"; +export { definition as faChartGantt } from "@fortawesome/free-solid-svg-icons/faChartGantt"; +export { definition as faChartLine } from "@fortawesome/free-solid-svg-icons/faChartLine"; +export { definition as faChartPie } from "@fortawesome/free-solid-svg-icons/faChartPie"; +export { definition as faChartSimple } from "@fortawesome/free-solid-svg-icons/faChartSimple"; +export { definition as faCheck } from "@fortawesome/free-solid-svg-icons/faCheck"; +export { definition as faCheckCircle } from "@fortawesome/free-solid-svg-icons/faCheckCircle"; +export { definition as faCheckDouble } from "@fortawesome/free-solid-svg-icons/faCheckDouble"; +export { definition as faCheckSquare } from "@fortawesome/free-solid-svg-icons/faCheckSquare"; +export { definition as faCheckToSlot } from "@fortawesome/free-solid-svg-icons/faCheckToSlot"; +export { definition as faCheese } from "@fortawesome/free-solid-svg-icons/faCheese"; +export { definition as faChess } from "@fortawesome/free-solid-svg-icons/faChess"; +export { definition as faChessBishop } from "@fortawesome/free-solid-svg-icons/faChessBishop"; +export { definition as faChessBoard } from "@fortawesome/free-solid-svg-icons/faChessBoard"; +export { definition as faChessKing } from "@fortawesome/free-solid-svg-icons/faChessKing"; +export { definition as faChessKnight } from "@fortawesome/free-solid-svg-icons/faChessKnight"; +export { definition as faChessPawn } from "@fortawesome/free-solid-svg-icons/faChessPawn"; +export { definition as faChessQueen } from "@fortawesome/free-solid-svg-icons/faChessQueen"; +export { definition as faChessRook } from "@fortawesome/free-solid-svg-icons/faChessRook"; +export { definition as faChevronCircleDown } from "@fortawesome/free-solid-svg-icons/faChevronCircleDown"; +export { definition as faChevronCircleLeft } from "@fortawesome/free-solid-svg-icons/faChevronCircleLeft"; +export { definition as faChevronCircleRight } from "@fortawesome/free-solid-svg-icons/faChevronCircleRight"; +export { definition as faChevronCircleUp } from "@fortawesome/free-solid-svg-icons/faChevronCircleUp"; +export { definition as faChevronDown } from "@fortawesome/free-solid-svg-icons/faChevronDown"; +export { definition as faChevronLeft } from "@fortawesome/free-solid-svg-icons/faChevronLeft"; +export { definition as faChevronRight } from "@fortawesome/free-solid-svg-icons/faChevronRight"; +export { definition as faChevronUp } from "@fortawesome/free-solid-svg-icons/faChevronUp"; +export { definition as faChild } from "@fortawesome/free-solid-svg-icons/faChild"; +export { definition as faChildCombatant } from "@fortawesome/free-solid-svg-icons/faChildCombatant"; +export { definition as faChildDress } from "@fortawesome/free-solid-svg-icons/faChildDress"; +export { definition as faChildReaching } from "@fortawesome/free-solid-svg-icons/faChildReaching"; +export { definition as faChildRifle } from "@fortawesome/free-solid-svg-icons/faChildRifle"; +export { definition as faChildren } from "@fortawesome/free-solid-svg-icons/faChildren"; +export { definition as faChurch } from "@fortawesome/free-solid-svg-icons/faChurch"; +export { definition as faCircle } from "@fortawesome/free-solid-svg-icons/faCircle"; +export { definition as faCircleArrowDown } from "@fortawesome/free-solid-svg-icons/faCircleArrowDown"; +export { definition as faCircleArrowLeft } from "@fortawesome/free-solid-svg-icons/faCircleArrowLeft"; +export { definition as faCircleArrowRight } from "@fortawesome/free-solid-svg-icons/faCircleArrowRight"; +export { definition as faCircleArrowUp } from "@fortawesome/free-solid-svg-icons/faCircleArrowUp"; +export { definition as faCircleCheck } from "@fortawesome/free-solid-svg-icons/faCircleCheck"; +export { definition as faCircleChevronDown } from "@fortawesome/free-solid-svg-icons/faCircleChevronDown"; +export { definition as faCircleChevronLeft } from "@fortawesome/free-solid-svg-icons/faCircleChevronLeft"; +export { definition as faCircleChevronRight } from "@fortawesome/free-solid-svg-icons/faCircleChevronRight"; +export { definition as faCircleChevronUp } from "@fortawesome/free-solid-svg-icons/faCircleChevronUp"; +export { definition as faCircleDollarToSlot } from "@fortawesome/free-solid-svg-icons/faCircleDollarToSlot"; +export { definition as faCircleDot } from "@fortawesome/free-solid-svg-icons/faCircleDot"; +export { definition as faCircleDown } from "@fortawesome/free-solid-svg-icons/faCircleDown"; +export { definition as faCircleExclamation } from "@fortawesome/free-solid-svg-icons/faCircleExclamation"; +export { definition as faCircleH } from "@fortawesome/free-solid-svg-icons/faCircleH"; +export { definition as faCircleHalfStroke } from "@fortawesome/free-solid-svg-icons/faCircleHalfStroke"; +export { definition as faCircleInfo } from "@fortawesome/free-solid-svg-icons/faCircleInfo"; +export { definition as faCircleLeft } from "@fortawesome/free-solid-svg-icons/faCircleLeft"; +export { definition as faCircleMinus } from "@fortawesome/free-solid-svg-icons/faCircleMinus"; +export { definition as faCircleNodes } from "@fortawesome/free-solid-svg-icons/faCircleNodes"; +export { definition as faCircleNotch } from "@fortawesome/free-solid-svg-icons/faCircleNotch"; +export { definition as faCirclePause } from "@fortawesome/free-solid-svg-icons/faCirclePause"; +export { definition as faCirclePlay } from "@fortawesome/free-solid-svg-icons/faCirclePlay"; +export { definition as faCirclePlus } from "@fortawesome/free-solid-svg-icons/faCirclePlus"; +export { definition as faCircleQuestion } from "@fortawesome/free-solid-svg-icons/faCircleQuestion"; +export { definition as faCircleRadiation } from "@fortawesome/free-solid-svg-icons/faCircleRadiation"; +export { definition as faCircleRight } from "@fortawesome/free-solid-svg-icons/faCircleRight"; +export { definition as faCircleStop } from "@fortawesome/free-solid-svg-icons/faCircleStop"; +export { definition as faCircleUp } from "@fortawesome/free-solid-svg-icons/faCircleUp"; +export { definition as faCircleUser } from "@fortawesome/free-solid-svg-icons/faCircleUser"; +export { definition as faCircleXmark } from "@fortawesome/free-solid-svg-icons/faCircleXmark"; +export { definition as faCity } from "@fortawesome/free-solid-svg-icons/faCity"; +export { definition as faClapperboard } from "@fortawesome/free-solid-svg-icons/faClapperboard"; +export { definition as faClinicMedical } from "@fortawesome/free-solid-svg-icons/faClinicMedical"; +export { definition as faClipboard } from "@fortawesome/free-solid-svg-icons/faClipboard"; +export { definition as faClipboardCheck } from "@fortawesome/free-solid-svg-icons/faClipboardCheck"; +export { definition as faClipboardList } from "@fortawesome/free-solid-svg-icons/faClipboardList"; +export { definition as faClipboardQuestion } from "@fortawesome/free-solid-svg-icons/faClipboardQuestion"; +export { definition as faClipboardUser } from "@fortawesome/free-solid-svg-icons/faClipboardUser"; +export { definition as faClock } from "@fortawesome/free-solid-svg-icons/faClock"; +export { definition as faClockFour } from "@fortawesome/free-solid-svg-icons/faClockFour"; +export { definition as faClockRotateLeft } from "@fortawesome/free-solid-svg-icons/faClockRotateLeft"; +export { definition as faClone } from "@fortawesome/free-solid-svg-icons/faClone"; +export { definition as faClose } from "@fortawesome/free-solid-svg-icons/faClose"; +export { definition as faClosedCaptioning } from "@fortawesome/free-solid-svg-icons/faClosedCaptioning"; +export { definition as faCloud } from "@fortawesome/free-solid-svg-icons/faCloud"; +export { definition as faCloudArrowDown } from "@fortawesome/free-solid-svg-icons/faCloudArrowDown"; +export { definition as faCloudArrowUp } from "@fortawesome/free-solid-svg-icons/faCloudArrowUp"; +export { definition as faCloudBolt } from "@fortawesome/free-solid-svg-icons/faCloudBolt"; +export { definition as faCloudDownload } from "@fortawesome/free-solid-svg-icons/faCloudDownload"; +export { definition as faCloudDownloadAlt } from "@fortawesome/free-solid-svg-icons/faCloudDownloadAlt"; +export { definition as faCloudMeatball } from "@fortawesome/free-solid-svg-icons/faCloudMeatball"; +export { definition as faCloudMoon } from "@fortawesome/free-solid-svg-icons/faCloudMoon"; +export { definition as faCloudMoonRain } from "@fortawesome/free-solid-svg-icons/faCloudMoonRain"; +export { definition as faCloudRain } from "@fortawesome/free-solid-svg-icons/faCloudRain"; +export { definition as faCloudShowersHeavy } from "@fortawesome/free-solid-svg-icons/faCloudShowersHeavy"; +export { definition as faCloudShowersWater } from "@fortawesome/free-solid-svg-icons/faCloudShowersWater"; +export { definition as faCloudSun } from "@fortawesome/free-solid-svg-icons/faCloudSun"; +export { definition as faCloudSunRain } from "@fortawesome/free-solid-svg-icons/faCloudSunRain"; +export { definition as faCloudUpload } from "@fortawesome/free-solid-svg-icons/faCloudUpload"; +export { definition as faCloudUploadAlt } from "@fortawesome/free-solid-svg-icons/faCloudUploadAlt"; +export { definition as faClover } from "@fortawesome/free-solid-svg-icons/faClover"; +export { definition as faCny } from "@fortawesome/free-solid-svg-icons/faCny"; +export { definition as faCocktail } from "@fortawesome/free-solid-svg-icons/faCocktail"; +export { definition as faCode } from "@fortawesome/free-solid-svg-icons/faCode"; +export { definition as faCodeBranch } from "@fortawesome/free-solid-svg-icons/faCodeBranch"; +export { definition as faCodeCommit } from "@fortawesome/free-solid-svg-icons/faCodeCommit"; +export { definition as faCodeCompare } from "@fortawesome/free-solid-svg-icons/faCodeCompare"; +export { definition as faCodeFork } from "@fortawesome/free-solid-svg-icons/faCodeFork"; +export { definition as faCodeMerge } from "@fortawesome/free-solid-svg-icons/faCodeMerge"; +export { definition as faCodePullRequest } from "@fortawesome/free-solid-svg-icons/faCodePullRequest"; +export { definition as faCoffee } from "@fortawesome/free-solid-svg-icons/faCoffee"; +export { definition as faCog } from "@fortawesome/free-solid-svg-icons/faCog"; +export { definition as faCogs } from "@fortawesome/free-solid-svg-icons/faCogs"; +export { definition as faCoins } from "@fortawesome/free-solid-svg-icons/faCoins"; +export { definition as faColonSign } from "@fortawesome/free-solid-svg-icons/faColonSign"; +export { definition as faColumns } from "@fortawesome/free-solid-svg-icons/faColumns"; +export { definition as faComment } from "@fortawesome/free-solid-svg-icons/faComment"; +export { definition as faCommentAlt } from "@fortawesome/free-solid-svg-icons/faCommentAlt"; +export { definition as faCommentDollar } from "@fortawesome/free-solid-svg-icons/faCommentDollar"; +export { definition as faCommentDots } from "@fortawesome/free-solid-svg-icons/faCommentDots"; +export { definition as faCommentMedical } from "@fortawesome/free-solid-svg-icons/faCommentMedical"; +export { definition as faCommentNodes } from "@fortawesome/free-solid-svg-icons/faCommentNodes"; +export { definition as faCommentSlash } from "@fortawesome/free-solid-svg-icons/faCommentSlash"; +export { definition as faCommentSms } from "@fortawesome/free-solid-svg-icons/faCommentSms"; +export { definition as faCommenting } from "@fortawesome/free-solid-svg-icons/faCommenting"; +export { definition as faComments } from "@fortawesome/free-solid-svg-icons/faComments"; +export { definition as faCommentsDollar } from "@fortawesome/free-solid-svg-icons/faCommentsDollar"; +export { definition as faCompactDisc } from "@fortawesome/free-solid-svg-icons/faCompactDisc"; +export { definition as faCompass } from "@fortawesome/free-solid-svg-icons/faCompass"; +export { definition as faCompassDrafting } from "@fortawesome/free-solid-svg-icons/faCompassDrafting"; +export { definition as faCompress } from "@fortawesome/free-solid-svg-icons/faCompress"; +export { definition as faCompressAlt } from "@fortawesome/free-solid-svg-icons/faCompressAlt"; +export { definition as faCompressArrowsAlt } from "@fortawesome/free-solid-svg-icons/faCompressArrowsAlt"; +export { definition as faComputer } from "@fortawesome/free-solid-svg-icons/faComputer"; +export { definition as faComputerMouse } from "@fortawesome/free-solid-svg-icons/faComputerMouse"; +export { definition as faConciergeBell } from "@fortawesome/free-solid-svg-icons/faConciergeBell"; +export { definition as faContactBook } from "@fortawesome/free-solid-svg-icons/faContactBook"; +export { definition as faContactCard } from "@fortawesome/free-solid-svg-icons/faContactCard"; +export { definition as faCookie } from "@fortawesome/free-solid-svg-icons/faCookie"; +export { definition as faCookieBite } from "@fortawesome/free-solid-svg-icons/faCookieBite"; +export { definition as faCopy } from "@fortawesome/free-solid-svg-icons/faCopy"; +export { definition as faCopyright } from "@fortawesome/free-solid-svg-icons/faCopyright"; +export { definition as faCouch } from "@fortawesome/free-solid-svg-icons/faCouch"; +export { definition as faCow } from "@fortawesome/free-solid-svg-icons/faCow"; +export { definition as faCreditCard } from "@fortawesome/free-solid-svg-icons/faCreditCard"; +export { definition as faCreditCardAlt } from "@fortawesome/free-solid-svg-icons/faCreditCardAlt"; +export { definition as faCrop } from "@fortawesome/free-solid-svg-icons/faCrop"; +export { definition as faCropAlt } from "@fortawesome/free-solid-svg-icons/faCropAlt"; +export { definition as faCropSimple } from "@fortawesome/free-solid-svg-icons/faCropSimple"; +export { definition as faCross } from "@fortawesome/free-solid-svg-icons/faCross"; +export { definition as faCrosshairs } from "@fortawesome/free-solid-svg-icons/faCrosshairs"; +export { definition as faCrow } from "@fortawesome/free-solid-svg-icons/faCrow"; +export { definition as faCrown } from "@fortawesome/free-solid-svg-icons/faCrown"; +export { definition as faCrutch } from "@fortawesome/free-solid-svg-icons/faCrutch"; +export { definition as faCruzeiroSign } from "@fortawesome/free-solid-svg-icons/faCruzeiroSign"; +export { definition as faCube } from "@fortawesome/free-solid-svg-icons/faCube"; +export { definition as faCubes } from "@fortawesome/free-solid-svg-icons/faCubes"; +export { definition as faCubesStacked } from "@fortawesome/free-solid-svg-icons/faCubesStacked"; +export { definition as faCut } from "@fortawesome/free-solid-svg-icons/faCut"; +export { definition as faCutlery } from "@fortawesome/free-solid-svg-icons/faCutlery"; +export { definition as faD } from "@fortawesome/free-solid-svg-icons/faD"; +export { definition as faDashboard } from "@fortawesome/free-solid-svg-icons/faDashboard"; +export { definition as faDatabase } from "@fortawesome/free-solid-svg-icons/faDatabase"; +export { definition as faDeaf } from "@fortawesome/free-solid-svg-icons/faDeaf"; +export { definition as faDeafness } from "@fortawesome/free-solid-svg-icons/faDeafness"; +export { definition as faDedent } from "@fortawesome/free-solid-svg-icons/faDedent"; +export { definition as faDeleteLeft } from "@fortawesome/free-solid-svg-icons/faDeleteLeft"; +export { definition as faDemocrat } from "@fortawesome/free-solid-svg-icons/faDemocrat"; +export { definition as faDesktop } from "@fortawesome/free-solid-svg-icons/faDesktop"; +export { definition as faDesktopAlt } from "@fortawesome/free-solid-svg-icons/faDesktopAlt"; +export { definition as faDharmachakra } from "@fortawesome/free-solid-svg-icons/faDharmachakra"; +export { definition as faDiagnoses } from "@fortawesome/free-solid-svg-icons/faDiagnoses"; +export { definition as faDiagramNext } from "@fortawesome/free-solid-svg-icons/faDiagramNext"; +export { definition as faDiagramPredecessor } from "@fortawesome/free-solid-svg-icons/faDiagramPredecessor"; +export { definition as faDiagramProject } from "@fortawesome/free-solid-svg-icons/faDiagramProject"; +export { definition as faDiagramSuccessor } from "@fortawesome/free-solid-svg-icons/faDiagramSuccessor"; +export { definition as faDiamond } from "@fortawesome/free-solid-svg-icons/faDiamond"; +export { definition as faDiamondTurnRight } from "@fortawesome/free-solid-svg-icons/faDiamondTurnRight"; +export { definition as faDice } from "@fortawesome/free-solid-svg-icons/faDice"; +export { definition as faDiceD20 } from "@fortawesome/free-solid-svg-icons/faDiceD20"; +export { definition as faDiceD6 } from "@fortawesome/free-solid-svg-icons/faDiceD6"; +export { definition as faDiceFive } from "@fortawesome/free-solid-svg-icons/faDiceFive"; +export { definition as faDiceFour } from "@fortawesome/free-solid-svg-icons/faDiceFour"; +export { definition as faDiceOne } from "@fortawesome/free-solid-svg-icons/faDiceOne"; +export { definition as faDiceSix } from "@fortawesome/free-solid-svg-icons/faDiceSix"; +export { definition as faDiceThree } from "@fortawesome/free-solid-svg-icons/faDiceThree"; +export { definition as faDiceTwo } from "@fortawesome/free-solid-svg-icons/faDiceTwo"; +export { definition as faDigging } from "@fortawesome/free-solid-svg-icons/faDigging"; +export { definition as faDigitalTachograph } from "@fortawesome/free-solid-svg-icons/faDigitalTachograph"; +export { definition as faDirections } from "@fortawesome/free-solid-svg-icons/faDirections"; +export { definition as faDisease } from "@fortawesome/free-solid-svg-icons/faDisease"; +export { definition as faDisplay } from "@fortawesome/free-solid-svg-icons/faDisplay"; +export { definition as faDivide } from "@fortawesome/free-solid-svg-icons/faDivide"; +export { definition as faDizzy } from "@fortawesome/free-solid-svg-icons/faDizzy"; +export { definition as faDna } from "@fortawesome/free-solid-svg-icons/faDna"; +export { definition as faDog } from "@fortawesome/free-solid-svg-icons/faDog"; +export { definition as faDollar } from "@fortawesome/free-solid-svg-icons/faDollar"; +export { definition as faDollarSign } from "@fortawesome/free-solid-svg-icons/faDollarSign"; +export { definition as faDolly } from "@fortawesome/free-solid-svg-icons/faDolly"; +export { definition as faDollyBox } from "@fortawesome/free-solid-svg-icons/faDollyBox"; +export { definition as faDollyFlatbed } from "@fortawesome/free-solid-svg-icons/faDollyFlatbed"; +export { definition as faDonate } from "@fortawesome/free-solid-svg-icons/faDonate"; +export { definition as faDongSign } from "@fortawesome/free-solid-svg-icons/faDongSign"; +export { definition as faDoorClosed } from "@fortawesome/free-solid-svg-icons/faDoorClosed"; +export { definition as faDoorOpen } from "@fortawesome/free-solid-svg-icons/faDoorOpen"; +export { definition as faDotCircle } from "@fortawesome/free-solid-svg-icons/faDotCircle"; +export { definition as faDove } from "@fortawesome/free-solid-svg-icons/faDove"; +export { definition as faDownLeftAndUpRightToCenter } from "@fortawesome/free-solid-svg-icons/faDownLeftAndUpRightToCenter"; +export { definition as faDownLong } from "@fortawesome/free-solid-svg-icons/faDownLong"; +export { definition as faDownload } from "@fortawesome/free-solid-svg-icons/faDownload"; +export { definition as faDraftingCompass } from "@fortawesome/free-solid-svg-icons/faDraftingCompass"; +export { definition as faDragon } from "@fortawesome/free-solid-svg-icons/faDragon"; +export { definition as faDrawPolygon } from "@fortawesome/free-solid-svg-icons/faDrawPolygon"; +export { definition as faDriversLicense } from "@fortawesome/free-solid-svg-icons/faDriversLicense"; +export { definition as faDroplet } from "@fortawesome/free-solid-svg-icons/faDroplet"; +export { definition as faDropletSlash } from "@fortawesome/free-solid-svg-icons/faDropletSlash"; +export { definition as faDrum } from "@fortawesome/free-solid-svg-icons/faDrum"; +export { definition as faDrumSteelpan } from "@fortawesome/free-solid-svg-icons/faDrumSteelpan"; +export { definition as faDrumstickBite } from "@fortawesome/free-solid-svg-icons/faDrumstickBite"; +export { definition as faDumbbell } from "@fortawesome/free-solid-svg-icons/faDumbbell"; +export { definition as faDumpster } from "@fortawesome/free-solid-svg-icons/faDumpster"; +export { definition as faDumpsterFire } from "@fortawesome/free-solid-svg-icons/faDumpsterFire"; +export { definition as faDungeon } from "@fortawesome/free-solid-svg-icons/faDungeon"; +export { definition as faE } from "@fortawesome/free-solid-svg-icons/faE"; +export { definition as faEarDeaf } from "@fortawesome/free-solid-svg-icons/faEarDeaf"; +export { definition as faEarListen } from "@fortawesome/free-solid-svg-icons/faEarListen"; +export { definition as faEarth } from "@fortawesome/free-solid-svg-icons/faEarth"; +export { definition as faEarthAfrica } from "@fortawesome/free-solid-svg-icons/faEarthAfrica"; +export { definition as faEarthAmerica } from "@fortawesome/free-solid-svg-icons/faEarthAmerica"; +export { definition as faEarthAmericas } from "@fortawesome/free-solid-svg-icons/faEarthAmericas"; +export { definition as faEarthAsia } from "@fortawesome/free-solid-svg-icons/faEarthAsia"; +export { definition as faEarthEurope } from "@fortawesome/free-solid-svg-icons/faEarthEurope"; +export { definition as faEarthOceania } from "@fortawesome/free-solid-svg-icons/faEarthOceania"; +export { definition as faEdit } from "@fortawesome/free-solid-svg-icons/faEdit"; +export { definition as faEgg } from "@fortawesome/free-solid-svg-icons/faEgg"; +export { definition as faEject } from "@fortawesome/free-solid-svg-icons/faEject"; +export { definition as faElevator } from "@fortawesome/free-solid-svg-icons/faElevator"; +export { definition as faEllipsis } from "@fortawesome/free-solid-svg-icons/faEllipsis"; +export { definition as faEllipsisH } from "@fortawesome/free-solid-svg-icons/faEllipsisH"; +export { definition as faEllipsisV } from "@fortawesome/free-solid-svg-icons/faEllipsisV"; +export { definition as faEllipsisVertical } from "@fortawesome/free-solid-svg-icons/faEllipsisVertical"; +export { definition as faEnvelope } from "@fortawesome/free-solid-svg-icons/faEnvelope"; +export { definition as faEnvelopeCircleCheck } from "@fortawesome/free-solid-svg-icons/faEnvelopeCircleCheck"; +export { definition as faEnvelopeOpen } from "@fortawesome/free-solid-svg-icons/faEnvelopeOpen"; +export { definition as faEnvelopeOpenText } from "@fortawesome/free-solid-svg-icons/faEnvelopeOpenText"; +export { definition as faEnvelopeSquare } from "@fortawesome/free-solid-svg-icons/faEnvelopeSquare"; +export { definition as faEnvelopesBulk } from "@fortawesome/free-solid-svg-icons/faEnvelopesBulk"; +export { definition as faEquals } from "@fortawesome/free-solid-svg-icons/faEquals"; +export { definition as faEraser } from "@fortawesome/free-solid-svg-icons/faEraser"; +export { definition as faEthernet } from "@fortawesome/free-solid-svg-icons/faEthernet"; +export { definition as faEur } from "@fortawesome/free-solid-svg-icons/faEur"; +export { definition as faEuro } from "@fortawesome/free-solid-svg-icons/faEuro"; +export { definition as faEuroSign } from "@fortawesome/free-solid-svg-icons/faEuroSign"; +export { definition as faExchange } from "@fortawesome/free-solid-svg-icons/faExchange"; +export { definition as faExchangeAlt } from "@fortawesome/free-solid-svg-icons/faExchangeAlt"; +export { definition as faExclamation } from "@fortawesome/free-solid-svg-icons/faExclamation"; +export { definition as faExclamationCircle } from "@fortawesome/free-solid-svg-icons/faExclamationCircle"; +export { definition as faExclamationTriangle } from "@fortawesome/free-solid-svg-icons/faExclamationTriangle"; +export { definition as faExpand } from "@fortawesome/free-solid-svg-icons/faExpand"; +export { definition as faExpandAlt } from "@fortawesome/free-solid-svg-icons/faExpandAlt"; +export { definition as faExpandArrowsAlt } from "@fortawesome/free-solid-svg-icons/faExpandArrowsAlt"; +export { definition as faExplosion } from "@fortawesome/free-solid-svg-icons/faExplosion"; +export { definition as faExternalLink } from "@fortawesome/free-solid-svg-icons/faExternalLink"; +export { definition as faExternalLinkAlt } from "@fortawesome/free-solid-svg-icons/faExternalLinkAlt"; +export { definition as faExternalLinkSquare } from "@fortawesome/free-solid-svg-icons/faExternalLinkSquare"; +export { definition as faExternalLinkSquareAlt } from "@fortawesome/free-solid-svg-icons/faExternalLinkSquareAlt"; +export { definition as faEye } from "@fortawesome/free-solid-svg-icons/faEye"; +export { definition as faEyeDropper } from "@fortawesome/free-solid-svg-icons/faEyeDropper"; +export { definition as faEyeDropperEmpty } from "@fortawesome/free-solid-svg-icons/faEyeDropperEmpty"; +export { definition as faEyeLowVision } from "@fortawesome/free-solid-svg-icons/faEyeLowVision"; +export { definition as faEyeSlash } from "@fortawesome/free-solid-svg-icons/faEyeSlash"; +export { definition as faF } from "@fortawesome/free-solid-svg-icons/faF"; +export { definition as faFaceAngry } from "@fortawesome/free-solid-svg-icons/faFaceAngry"; +export { definition as faFaceDizzy } from "@fortawesome/free-solid-svg-icons/faFaceDizzy"; +export { definition as faFaceFlushed } from "@fortawesome/free-solid-svg-icons/faFaceFlushed"; +export { definition as faFaceFrown } from "@fortawesome/free-solid-svg-icons/faFaceFrown"; +export { definition as faFaceFrownOpen } from "@fortawesome/free-solid-svg-icons/faFaceFrownOpen"; +export { definition as faFaceGrimace } from "@fortawesome/free-solid-svg-icons/faFaceGrimace"; +export { definition as faFaceGrin } from "@fortawesome/free-solid-svg-icons/faFaceGrin"; +export { definition as faFaceGrinBeam } from "@fortawesome/free-solid-svg-icons/faFaceGrinBeam"; +export { definition as faFaceGrinBeamSweat } from "@fortawesome/free-solid-svg-icons/faFaceGrinBeamSweat"; +export { definition as faFaceGrinHearts } from "@fortawesome/free-solid-svg-icons/faFaceGrinHearts"; +export { definition as faFaceGrinSquint } from "@fortawesome/free-solid-svg-icons/faFaceGrinSquint"; +export { definition as faFaceGrinSquintTears } from "@fortawesome/free-solid-svg-icons/faFaceGrinSquintTears"; +export { definition as faFaceGrinStars } from "@fortawesome/free-solid-svg-icons/faFaceGrinStars"; +export { definition as faFaceGrinTears } from "@fortawesome/free-solid-svg-icons/faFaceGrinTears"; +export { definition as faFaceGrinTongue } from "@fortawesome/free-solid-svg-icons/faFaceGrinTongue"; +export { definition as faFaceGrinTongueSquint } from "@fortawesome/free-solid-svg-icons/faFaceGrinTongueSquint"; +export { definition as faFaceGrinTongueWink } from "@fortawesome/free-solid-svg-icons/faFaceGrinTongueWink"; +export { definition as faFaceGrinWide } from "@fortawesome/free-solid-svg-icons/faFaceGrinWide"; +export { definition as faFaceGrinWink } from "@fortawesome/free-solid-svg-icons/faFaceGrinWink"; +export { definition as faFaceKiss } from "@fortawesome/free-solid-svg-icons/faFaceKiss"; +export { definition as faFaceKissBeam } from "@fortawesome/free-solid-svg-icons/faFaceKissBeam"; +export { definition as faFaceKissWinkHeart } from "@fortawesome/free-solid-svg-icons/faFaceKissWinkHeart"; +export { definition as faFaceLaugh } from "@fortawesome/free-solid-svg-icons/faFaceLaugh"; +export { definition as faFaceLaughBeam } from "@fortawesome/free-solid-svg-icons/faFaceLaughBeam"; +export { definition as faFaceLaughSquint } from "@fortawesome/free-solid-svg-icons/faFaceLaughSquint"; +export { definition as faFaceLaughWink } from "@fortawesome/free-solid-svg-icons/faFaceLaughWink"; +export { definition as faFaceMeh } from "@fortawesome/free-solid-svg-icons/faFaceMeh"; +export { definition as faFaceMehBlank } from "@fortawesome/free-solid-svg-icons/faFaceMehBlank"; +export { definition as faFaceRollingEyes } from "@fortawesome/free-solid-svg-icons/faFaceRollingEyes"; +export { definition as faFaceSadCry } from "@fortawesome/free-solid-svg-icons/faFaceSadCry"; +export { definition as faFaceSadTear } from "@fortawesome/free-solid-svg-icons/faFaceSadTear"; +export { definition as faFaceSmile } from "@fortawesome/free-solid-svg-icons/faFaceSmile"; +export { definition as faFaceSmileBeam } from "@fortawesome/free-solid-svg-icons/faFaceSmileBeam"; +export { definition as faFaceSmileWink } from "@fortawesome/free-solid-svg-icons/faFaceSmileWink"; +export { definition as faFaceSurprise } from "@fortawesome/free-solid-svg-icons/faFaceSurprise"; +export { definition as faFaceTired } from "@fortawesome/free-solid-svg-icons/faFaceTired"; +export { definition as faFan } from "@fortawesome/free-solid-svg-icons/faFan"; +export { definition as faFastBackward } from "@fortawesome/free-solid-svg-icons/faFastBackward"; +export { definition as faFastForward } from "@fortawesome/free-solid-svg-icons/faFastForward"; +export { definition as faFaucet } from "@fortawesome/free-solid-svg-icons/faFaucet"; +export { definition as faFaucetDrip } from "@fortawesome/free-solid-svg-icons/faFaucetDrip"; +export { definition as faFax } from "@fortawesome/free-solid-svg-icons/faFax"; +export { definition as faFeather } from "@fortawesome/free-solid-svg-icons/faFeather"; +export { definition as faFeatherAlt } from "@fortawesome/free-solid-svg-icons/faFeatherAlt"; +export { definition as faFeatherPointed } from "@fortawesome/free-solid-svg-icons/faFeatherPointed"; +export { definition as faFeed } from "@fortawesome/free-solid-svg-icons/faFeed"; +export { definition as faFemale } from "@fortawesome/free-solid-svg-icons/faFemale"; +export { definition as faFerry } from "@fortawesome/free-solid-svg-icons/faFerry"; +export { definition as faFighterJet } from "@fortawesome/free-solid-svg-icons/faFighterJet"; +export { definition as faFile } from "@fortawesome/free-solid-svg-icons/faFile"; +export { definition as faFileAlt } from "@fortawesome/free-solid-svg-icons/faFileAlt"; +export { definition as faFileArchive } from "@fortawesome/free-solid-svg-icons/faFileArchive"; +export { definition as faFileArrowDown } from "@fortawesome/free-solid-svg-icons/faFileArrowDown"; +export { definition as faFileArrowUp } from "@fortawesome/free-solid-svg-icons/faFileArrowUp"; +export { definition as faFileAudio } from "@fortawesome/free-solid-svg-icons/faFileAudio"; +export { definition as faFileCircleCheck } from "@fortawesome/free-solid-svg-icons/faFileCircleCheck"; +export { definition as faFileCircleExclamation } from "@fortawesome/free-solid-svg-icons/faFileCircleExclamation"; +export { definition as faFileCircleMinus } from "@fortawesome/free-solid-svg-icons/faFileCircleMinus"; +export { definition as faFileCirclePlus } from "@fortawesome/free-solid-svg-icons/faFileCirclePlus"; +export { definition as faFileCircleQuestion } from "@fortawesome/free-solid-svg-icons/faFileCircleQuestion"; +export { definition as faFileCircleXmark } from "@fortawesome/free-solid-svg-icons/faFileCircleXmark"; +export { definition as faFileClipboard } from "@fortawesome/free-solid-svg-icons/faFileClipboard"; +export { definition as faFileCode } from "@fortawesome/free-solid-svg-icons/faFileCode"; +export { definition as faFileContract } from "@fortawesome/free-solid-svg-icons/faFileContract"; +export { definition as faFileCsv } from "@fortawesome/free-solid-svg-icons/faFileCsv"; +export { definition as faFileDownload } from "@fortawesome/free-solid-svg-icons/faFileDownload"; +export { definition as faFileEdit } from "@fortawesome/free-solid-svg-icons/faFileEdit"; +export { definition as faFileExcel } from "@fortawesome/free-solid-svg-icons/faFileExcel"; +export { definition as faFileExport } from "@fortawesome/free-solid-svg-icons/faFileExport"; +export { definition as faFileFragment } from "@fortawesome/free-solid-svg-icons/faFileFragment"; +export { definition as faFileHalfDashed } from "@fortawesome/free-solid-svg-icons/faFileHalfDashed"; +export { definition as faFileImage } from "@fortawesome/free-solid-svg-icons/faFileImage"; +export { definition as faFileImport } from "@fortawesome/free-solid-svg-icons/faFileImport"; +export { definition as faFileInvoice } from "@fortawesome/free-solid-svg-icons/faFileInvoice"; +export { definition as faFileInvoiceDollar } from "@fortawesome/free-solid-svg-icons/faFileInvoiceDollar"; +export { definition as faFileLines } from "@fortawesome/free-solid-svg-icons/faFileLines"; +export { definition as faFileMedical } from "@fortawesome/free-solid-svg-icons/faFileMedical"; +export { definition as faFileMedicalAlt } from "@fortawesome/free-solid-svg-icons/faFileMedicalAlt"; +export { definition as faFilePdf } from "@fortawesome/free-solid-svg-icons/faFilePdf"; +export { definition as faFilePen } from "@fortawesome/free-solid-svg-icons/faFilePen"; +export { definition as faFilePowerpoint } from "@fortawesome/free-solid-svg-icons/faFilePowerpoint"; +export { definition as faFilePrescription } from "@fortawesome/free-solid-svg-icons/faFilePrescription"; +export { definition as faFileShield } from "@fortawesome/free-solid-svg-icons/faFileShield"; +export { definition as faFileSignature } from "@fortawesome/free-solid-svg-icons/faFileSignature"; +export { definition as faFileText } from "@fortawesome/free-solid-svg-icons/faFileText"; +export { definition as faFileUpload } from "@fortawesome/free-solid-svg-icons/faFileUpload"; +export { definition as faFileVideo } from "@fortawesome/free-solid-svg-icons/faFileVideo"; +export { definition as faFileWaveform } from "@fortawesome/free-solid-svg-icons/faFileWaveform"; +export { definition as faFileWord } from "@fortawesome/free-solid-svg-icons/faFileWord"; +export { definition as faFileZipper } from "@fortawesome/free-solid-svg-icons/faFileZipper"; +export { definition as faFill } from "@fortawesome/free-solid-svg-icons/faFill"; +export { definition as faFillDrip } from "@fortawesome/free-solid-svg-icons/faFillDrip"; +export { definition as faFilm } from "@fortawesome/free-solid-svg-icons/faFilm"; +export { definition as faFilter } from "@fortawesome/free-solid-svg-icons/faFilter"; +export { definition as faFilterCircleDollar } from "@fortawesome/free-solid-svg-icons/faFilterCircleDollar"; +export { definition as faFilterCircleXmark } from "@fortawesome/free-solid-svg-icons/faFilterCircleXmark"; +export { definition as faFingerprint } from "@fortawesome/free-solid-svg-icons/faFingerprint"; +export { definition as faFire } from "@fortawesome/free-solid-svg-icons/faFire"; +export { definition as faFireAlt } from "@fortawesome/free-solid-svg-icons/faFireAlt"; +export { definition as faFireBurner } from "@fortawesome/free-solid-svg-icons/faFireBurner"; +export { definition as faFireExtinguisher } from "@fortawesome/free-solid-svg-icons/faFireExtinguisher"; +export { definition as faFireFlameCurved } from "@fortawesome/free-solid-svg-icons/faFireFlameCurved"; +export { definition as faFireFlameSimple } from "@fortawesome/free-solid-svg-icons/faFireFlameSimple"; +export { definition as faFirstAid } from "@fortawesome/free-solid-svg-icons/faFirstAid"; +export { definition as faFish } from "@fortawesome/free-solid-svg-icons/faFish"; +export { definition as faFishFins } from "@fortawesome/free-solid-svg-icons/faFishFins"; +export { definition as faFistRaised } from "@fortawesome/free-solid-svg-icons/faFistRaised"; +export { definition as faFlag } from "@fortawesome/free-solid-svg-icons/faFlag"; +export { definition as faFlagCheckered } from "@fortawesome/free-solid-svg-icons/faFlagCheckered"; +export { definition as faFlagUsa } from "@fortawesome/free-solid-svg-icons/faFlagUsa"; +export { definition as faFlask } from "@fortawesome/free-solid-svg-icons/faFlask"; +export { definition as faFlaskVial } from "@fortawesome/free-solid-svg-icons/faFlaskVial"; +export { definition as faFloppyDisk } from "@fortawesome/free-solid-svg-icons/faFloppyDisk"; +export { definition as faFlorinSign } from "@fortawesome/free-solid-svg-icons/faFlorinSign"; +export { definition as faFlushed } from "@fortawesome/free-solid-svg-icons/faFlushed"; +export { definition as faFolder } from "@fortawesome/free-solid-svg-icons/faFolder"; +export { definition as faFolderBlank } from "@fortawesome/free-solid-svg-icons/faFolderBlank"; +export { definition as faFolderClosed } from "@fortawesome/free-solid-svg-icons/faFolderClosed"; +export { definition as faFolderMinus } from "@fortawesome/free-solid-svg-icons/faFolderMinus"; +export { definition as faFolderOpen } from "@fortawesome/free-solid-svg-icons/faFolderOpen"; +export { definition as faFolderPlus } from "@fortawesome/free-solid-svg-icons/faFolderPlus"; +export { definition as faFolderTree } from "@fortawesome/free-solid-svg-icons/faFolderTree"; +export { definition as faFont } from "@fortawesome/free-solid-svg-icons/faFont"; +export { definition as faFontAwesome } from "@fortawesome/free-solid-svg-icons/faFontAwesome"; +export { definition as faFontAwesomeFlag } from "@fortawesome/free-solid-svg-icons/faFontAwesomeFlag"; +export { definition as faFontAwesomeLogoFull } from "@fortawesome/free-solid-svg-icons/faFontAwesomeLogoFull"; +export { definition as faFootball } from "@fortawesome/free-solid-svg-icons/faFootball"; +export { definition as faFootballBall } from "@fortawesome/free-solid-svg-icons/faFootballBall"; +export { definition as faForward } from "@fortawesome/free-solid-svg-icons/faForward"; +export { definition as faForwardFast } from "@fortawesome/free-solid-svg-icons/faForwardFast"; +export { definition as faForwardStep } from "@fortawesome/free-solid-svg-icons/faForwardStep"; +export { definition as faFrancSign } from "@fortawesome/free-solid-svg-icons/faFrancSign"; +export { definition as faFrog } from "@fortawesome/free-solid-svg-icons/faFrog"; +export { definition as faFrown } from "@fortawesome/free-solid-svg-icons/faFrown"; +export { definition as faFrownOpen } from "@fortawesome/free-solid-svg-icons/faFrownOpen"; +export { definition as faFunnelDollar } from "@fortawesome/free-solid-svg-icons/faFunnelDollar"; +export { definition as faFutbol } from "@fortawesome/free-solid-svg-icons/faFutbol"; +export { definition as faFutbolBall } from "@fortawesome/free-solid-svg-icons/faFutbolBall"; +export { definition as faG } from "@fortawesome/free-solid-svg-icons/faG"; +export { definition as faGamepad } from "@fortawesome/free-solid-svg-icons/faGamepad"; +export { definition as faGasPump } from "@fortawesome/free-solid-svg-icons/faGasPump"; +export { definition as faGauge } from "@fortawesome/free-solid-svg-icons/faGauge"; +export { definition as faGaugeHigh } from "@fortawesome/free-solid-svg-icons/faGaugeHigh"; +export { definition as faGaugeMed } from "@fortawesome/free-solid-svg-icons/faGaugeMed"; +export { definition as faGaugeSimple } from "@fortawesome/free-solid-svg-icons/faGaugeSimple"; +export { definition as faGaugeSimpleHigh } from "@fortawesome/free-solid-svg-icons/faGaugeSimpleHigh"; +export { definition as faGaugeSimpleMed } from "@fortawesome/free-solid-svg-icons/faGaugeSimpleMed"; +export { definition as faGavel } from "@fortawesome/free-solid-svg-icons/faGavel"; +export { definition as faGbp } from "@fortawesome/free-solid-svg-icons/faGbp"; +export { definition as faGear } from "@fortawesome/free-solid-svg-icons/faGear"; +export { definition as faGears } from "@fortawesome/free-solid-svg-icons/faGears"; +export { definition as faGem } from "@fortawesome/free-solid-svg-icons/faGem"; +export { definition as faGenderless } from "@fortawesome/free-solid-svg-icons/faGenderless"; +export { definition as faGhost } from "@fortawesome/free-solid-svg-icons/faGhost"; +export { definition as faGift } from "@fortawesome/free-solid-svg-icons/faGift"; +export { definition as faGifts } from "@fortawesome/free-solid-svg-icons/faGifts"; +export { definition as faGlassCheers } from "@fortawesome/free-solid-svg-icons/faGlassCheers"; +export { definition as faGlassMartini } from "@fortawesome/free-solid-svg-icons/faGlassMartini"; +export { definition as faGlassMartiniAlt } from "@fortawesome/free-solid-svg-icons/faGlassMartiniAlt"; +export { definition as faGlassWater } from "@fortawesome/free-solid-svg-icons/faGlassWater"; +export { definition as faGlassWaterDroplet } from "@fortawesome/free-solid-svg-icons/faGlassWaterDroplet"; +export { definition as faGlassWhiskey } from "@fortawesome/free-solid-svg-icons/faGlassWhiskey"; +export { definition as faGlasses } from "@fortawesome/free-solid-svg-icons/faGlasses"; +export { definition as faGlobe } from "@fortawesome/free-solid-svg-icons/faGlobe"; +export { definition as faGlobeAfrica } from "@fortawesome/free-solid-svg-icons/faGlobeAfrica"; +export { definition as faGlobeAmericas } from "@fortawesome/free-solid-svg-icons/faGlobeAmericas"; +export { definition as faGlobeAsia } from "@fortawesome/free-solid-svg-icons/faGlobeAsia"; +export { definition as faGlobeEurope } from "@fortawesome/free-solid-svg-icons/faGlobeEurope"; +export { definition as faGlobeOceania } from "@fortawesome/free-solid-svg-icons/faGlobeOceania"; +export { definition as faGolfBall } from "@fortawesome/free-solid-svg-icons/faGolfBall"; +export { definition as faGolfBallTee } from "@fortawesome/free-solid-svg-icons/faGolfBallTee"; +export { definition as faGopuram } from "@fortawesome/free-solid-svg-icons/faGopuram"; +export { definition as faGraduationCap } from "@fortawesome/free-solid-svg-icons/faGraduationCap"; +export { definition as faGreaterThan } from "@fortawesome/free-solid-svg-icons/faGreaterThan"; +export { definition as faGreaterThanEqual } from "@fortawesome/free-solid-svg-icons/faGreaterThanEqual"; +export { definition as faGrimace } from "@fortawesome/free-solid-svg-icons/faGrimace"; +export { definition as faGrin } from "@fortawesome/free-solid-svg-icons/faGrin"; +export { definition as faGrinAlt } from "@fortawesome/free-solid-svg-icons/faGrinAlt"; +export { definition as faGrinBeam } from "@fortawesome/free-solid-svg-icons/faGrinBeam"; +export { definition as faGrinBeamSweat } from "@fortawesome/free-solid-svg-icons/faGrinBeamSweat"; +export { definition as faGrinHearts } from "@fortawesome/free-solid-svg-icons/faGrinHearts"; +export { definition as faGrinSquint } from "@fortawesome/free-solid-svg-icons/faGrinSquint"; +export { definition as faGrinSquintTears } from "@fortawesome/free-solid-svg-icons/faGrinSquintTears"; +export { definition as faGrinStars } from "@fortawesome/free-solid-svg-icons/faGrinStars"; +export { definition as faGrinTears } from "@fortawesome/free-solid-svg-icons/faGrinTears"; +export { definition as faGrinTongue } from "@fortawesome/free-solid-svg-icons/faGrinTongue"; +export { definition as faGrinTongueSquint } from "@fortawesome/free-solid-svg-icons/faGrinTongueSquint"; +export { definition as faGrinTongueWink } from "@fortawesome/free-solid-svg-icons/faGrinTongueWink"; +export { definition as faGrinWink } from "@fortawesome/free-solid-svg-icons/faGrinWink"; +export { definition as faGrip } from "@fortawesome/free-solid-svg-icons/faGrip"; +export { definition as faGripHorizontal } from "@fortawesome/free-solid-svg-icons/faGripHorizontal"; +export { definition as faGripLines } from "@fortawesome/free-solid-svg-icons/faGripLines"; +export { definition as faGripLinesVertical } from "@fortawesome/free-solid-svg-icons/faGripLinesVertical"; +export { definition as faGripVertical } from "@fortawesome/free-solid-svg-icons/faGripVertical"; +export { definition as faGroupArrowsRotate } from "@fortawesome/free-solid-svg-icons/faGroupArrowsRotate"; +export { definition as faGuaraniSign } from "@fortawesome/free-solid-svg-icons/faGuaraniSign"; +export { definition as faGuitar } from "@fortawesome/free-solid-svg-icons/faGuitar"; +export { definition as faGun } from "@fortawesome/free-solid-svg-icons/faGun"; +export { definition as faH } from "@fortawesome/free-solid-svg-icons/faH"; +export { definition as faHSquare } from "@fortawesome/free-solid-svg-icons/faHSquare"; +export { definition as faHamburger } from "@fortawesome/free-solid-svg-icons/faHamburger"; +export { definition as faHammer } from "@fortawesome/free-solid-svg-icons/faHammer"; +export { definition as faHamsa } from "@fortawesome/free-solid-svg-icons/faHamsa"; +export { definition as faHand } from "@fortawesome/free-solid-svg-icons/faHand"; +export { definition as faHandBackFist } from "@fortawesome/free-solid-svg-icons/faHandBackFist"; +export { definition as faHandDots } from "@fortawesome/free-solid-svg-icons/faHandDots"; +export { definition as faHandFist } from "@fortawesome/free-solid-svg-icons/faHandFist"; +export { definition as faHandHolding } from "@fortawesome/free-solid-svg-icons/faHandHolding"; +export { definition as faHandHoldingDollar } from "@fortawesome/free-solid-svg-icons/faHandHoldingDollar"; +export { definition as faHandHoldingDroplet } from "@fortawesome/free-solid-svg-icons/faHandHoldingDroplet"; +export { definition as faHandHoldingHand } from "@fortawesome/free-solid-svg-icons/faHandHoldingHand"; +export { definition as faHandHoldingHeart } from "@fortawesome/free-solid-svg-icons/faHandHoldingHeart"; +export { definition as faHandHoldingMedical } from "@fortawesome/free-solid-svg-icons/faHandHoldingMedical"; +export { definition as faHandHoldingUsd } from "@fortawesome/free-solid-svg-icons/faHandHoldingUsd"; +export { definition as faHandHoldingWater } from "@fortawesome/free-solid-svg-icons/faHandHoldingWater"; +export { definition as faHandLizard } from "@fortawesome/free-solid-svg-icons/faHandLizard"; +export { definition as faHandMiddleFinger } from "@fortawesome/free-solid-svg-icons/faHandMiddleFinger"; +export { definition as faHandPaper } from "@fortawesome/free-solid-svg-icons/faHandPaper"; +export { definition as faHandPeace } from "@fortawesome/free-solid-svg-icons/faHandPeace"; +export { definition as faHandPointDown } from "@fortawesome/free-solid-svg-icons/faHandPointDown"; +export { definition as faHandPointLeft } from "@fortawesome/free-solid-svg-icons/faHandPointLeft"; +export { definition as faHandPointRight } from "@fortawesome/free-solid-svg-icons/faHandPointRight"; +export { definition as faHandPointUp } from "@fortawesome/free-solid-svg-icons/faHandPointUp"; +export { definition as faHandPointer } from "@fortawesome/free-solid-svg-icons/faHandPointer"; +export { definition as faHandRock } from "@fortawesome/free-solid-svg-icons/faHandRock"; +export { definition as faHandScissors } from "@fortawesome/free-solid-svg-icons/faHandScissors"; +export { definition as faHandSparkles } from "@fortawesome/free-solid-svg-icons/faHandSparkles"; +export { definition as faHandSpock } from "@fortawesome/free-solid-svg-icons/faHandSpock"; +export { definition as faHandcuffs } from "@fortawesome/free-solid-svg-icons/faHandcuffs"; +export { definition as faHands } from "@fortawesome/free-solid-svg-icons/faHands"; +export { definition as faHandsAmericanSignLanguageInterpreting } from "@fortawesome/free-solid-svg-icons/faHandsAmericanSignLanguageInterpreting"; +export { definition as faHandsAslInterpreting } from "@fortawesome/free-solid-svg-icons/faHandsAslInterpreting"; +export { definition as faHandsBound } from "@fortawesome/free-solid-svg-icons/faHandsBound"; +export { definition as faHandsBubbles } from "@fortawesome/free-solid-svg-icons/faHandsBubbles"; +export { definition as faHandsClapping } from "@fortawesome/free-solid-svg-icons/faHandsClapping"; +export { definition as faHandsHelping } from "@fortawesome/free-solid-svg-icons/faHandsHelping"; +export { definition as faHandsHolding } from "@fortawesome/free-solid-svg-icons/faHandsHolding"; +export { definition as faHandsHoldingChild } from "@fortawesome/free-solid-svg-icons/faHandsHoldingChild"; +export { definition as faHandsHoldingCircle } from "@fortawesome/free-solid-svg-icons/faHandsHoldingCircle"; +export { definition as faHandsPraying } from "@fortawesome/free-solid-svg-icons/faHandsPraying"; +export { definition as faHandsWash } from "@fortawesome/free-solid-svg-icons/faHandsWash"; +export { definition as faHandshake } from "@fortawesome/free-solid-svg-icons/faHandshake"; +export { definition as faHandshakeAlt } from "@fortawesome/free-solid-svg-icons/faHandshakeAlt"; +export { definition as faHandshakeAltSlash } from "@fortawesome/free-solid-svg-icons/faHandshakeAltSlash"; +export { definition as faHandshakeAngle } from "@fortawesome/free-solid-svg-icons/faHandshakeAngle"; +export { definition as faHandshakeSimple } from "@fortawesome/free-solid-svg-icons/faHandshakeSimple"; +export { definition as faHandshakeSimpleSlash } from "@fortawesome/free-solid-svg-icons/faHandshakeSimpleSlash"; +export { definition as faHandshakeSlash } from "@fortawesome/free-solid-svg-icons/faHandshakeSlash"; +export { definition as faHanukiah } from "@fortawesome/free-solid-svg-icons/faHanukiah"; +export { definition as faHardDrive } from "@fortawesome/free-solid-svg-icons/faHardDrive"; +export { definition as faHardHat } from "@fortawesome/free-solid-svg-icons/faHardHat"; +export { definition as faHardOfHearing } from "@fortawesome/free-solid-svg-icons/faHardOfHearing"; +export { definition as faHashtag } from "@fortawesome/free-solid-svg-icons/faHashtag"; +export { definition as faHatCowboy } from "@fortawesome/free-solid-svg-icons/faHatCowboy"; +export { definition as faHatCowboySide } from "@fortawesome/free-solid-svg-icons/faHatCowboySide"; +export { definition as faHatHard } from "@fortawesome/free-solid-svg-icons/faHatHard"; +export { definition as faHatWizard } from "@fortawesome/free-solid-svg-icons/faHatWizard"; +export { definition as faHaykal } from "@fortawesome/free-solid-svg-icons/faHaykal"; +export { definition as faHdd } from "@fortawesome/free-solid-svg-icons/faHdd"; +export { definition as faHeadSideCough } from "@fortawesome/free-solid-svg-icons/faHeadSideCough"; +export { definition as faHeadSideCoughSlash } from "@fortawesome/free-solid-svg-icons/faHeadSideCoughSlash"; +export { definition as faHeadSideMask } from "@fortawesome/free-solid-svg-icons/faHeadSideMask"; +export { definition as faHeadSideVirus } from "@fortawesome/free-solid-svg-icons/faHeadSideVirus"; +export { definition as faHeader } from "@fortawesome/free-solid-svg-icons/faHeader"; +export { definition as faHeading } from "@fortawesome/free-solid-svg-icons/faHeading"; +export { definition as faHeadphones } from "@fortawesome/free-solid-svg-icons/faHeadphones"; +export { definition as faHeadphonesAlt } from "@fortawesome/free-solid-svg-icons/faHeadphonesAlt"; +export { definition as faHeadphonesSimple } from "@fortawesome/free-solid-svg-icons/faHeadphonesSimple"; +export { definition as faHeadset } from "@fortawesome/free-solid-svg-icons/faHeadset"; +export { definition as faHeart } from "@fortawesome/free-solid-svg-icons/faHeart"; +export { definition as faHeartBroken } from "@fortawesome/free-solid-svg-icons/faHeartBroken"; +export { definition as faHeartCircleBolt } from "@fortawesome/free-solid-svg-icons/faHeartCircleBolt"; +export { definition as faHeartCircleCheck } from "@fortawesome/free-solid-svg-icons/faHeartCircleCheck"; +export { definition as faHeartCircleExclamation } from "@fortawesome/free-solid-svg-icons/faHeartCircleExclamation"; +export { definition as faHeartCircleMinus } from "@fortawesome/free-solid-svg-icons/faHeartCircleMinus"; +export { definition as faHeartCirclePlus } from "@fortawesome/free-solid-svg-icons/faHeartCirclePlus"; +export { definition as faHeartCircleXmark } from "@fortawesome/free-solid-svg-icons/faHeartCircleXmark"; +export { definition as faHeartCrack } from "@fortawesome/free-solid-svg-icons/faHeartCrack"; +export { definition as faHeartMusicCameraBolt } from "@fortawesome/free-solid-svg-icons/faHeartMusicCameraBolt"; +export { definition as faHeartPulse } from "@fortawesome/free-solid-svg-icons/faHeartPulse"; +export { definition as faHeartbeat } from "@fortawesome/free-solid-svg-icons/faHeartbeat"; +export { definition as faHelicopter } from "@fortawesome/free-solid-svg-icons/faHelicopter"; +export { definition as faHelicopterSymbol } from "@fortawesome/free-solid-svg-icons/faHelicopterSymbol"; +export { definition as faHelmetSafety } from "@fortawesome/free-solid-svg-icons/faHelmetSafety"; +export { definition as faHelmetUn } from "@fortawesome/free-solid-svg-icons/faHelmetUn"; +export { definition as faHexagonNodes } from "@fortawesome/free-solid-svg-icons/faHexagonNodes"; +export { definition as faHexagonNodesBolt } from "@fortawesome/free-solid-svg-icons/faHexagonNodesBolt"; +export { definition as faHighlighter } from "@fortawesome/free-solid-svg-icons/faHighlighter"; +export { definition as faHiking } from "@fortawesome/free-solid-svg-icons/faHiking"; +export { definition as faHillAvalanche } from "@fortawesome/free-solid-svg-icons/faHillAvalanche"; +export { definition as faHillRockslide } from "@fortawesome/free-solid-svg-icons/faHillRockslide"; +export { definition as faHippo } from "@fortawesome/free-solid-svg-icons/faHippo"; +export { definition as faHistory } from "@fortawesome/free-solid-svg-icons/faHistory"; +export { definition as faHockeyPuck } from "@fortawesome/free-solid-svg-icons/faHockeyPuck"; +export { definition as faHollyBerry } from "@fortawesome/free-solid-svg-icons/faHollyBerry"; +export { definition as faHome } from "@fortawesome/free-solid-svg-icons/faHome"; +export { definition as faHomeAlt } from "@fortawesome/free-solid-svg-icons/faHomeAlt"; +export { definition as faHomeLg } from "@fortawesome/free-solid-svg-icons/faHomeLg"; +export { definition as faHomeLgAlt } from "@fortawesome/free-solid-svg-icons/faHomeLgAlt"; +export { definition as faHomeUser } from "@fortawesome/free-solid-svg-icons/faHomeUser"; +export { definition as faHorse } from "@fortawesome/free-solid-svg-icons/faHorse"; +export { definition as faHorseHead } from "@fortawesome/free-solid-svg-icons/faHorseHead"; +export { definition as faHospital } from "@fortawesome/free-solid-svg-icons/faHospital"; +export { definition as faHospitalAlt } from "@fortawesome/free-solid-svg-icons/faHospitalAlt"; +export { definition as faHospitalSymbol } from "@fortawesome/free-solid-svg-icons/faHospitalSymbol"; +export { definition as faHospitalUser } from "@fortawesome/free-solid-svg-icons/faHospitalUser"; +export { definition as faHospitalWide } from "@fortawesome/free-solid-svg-icons/faHospitalWide"; +export { definition as faHotTub } from "@fortawesome/free-solid-svg-icons/faHotTub"; +export { definition as faHotTubPerson } from "@fortawesome/free-solid-svg-icons/faHotTubPerson"; +export { definition as faHotdog } from "@fortawesome/free-solid-svg-icons/faHotdog"; +export { definition as faHotel } from "@fortawesome/free-solid-svg-icons/faHotel"; +export { definition as faHourglass } from "@fortawesome/free-solid-svg-icons/faHourglass"; +export { definition as faHourglass1 } from "@fortawesome/free-solid-svg-icons/faHourglass1"; +export { definition as faHourglass2 } from "@fortawesome/free-solid-svg-icons/faHourglass2"; +export { definition as faHourglass3 } from "@fortawesome/free-solid-svg-icons/faHourglass3"; +export { definition as faHourglassEmpty } from "@fortawesome/free-solid-svg-icons/faHourglassEmpty"; +export { definition as faHourglassEnd } from "@fortawesome/free-solid-svg-icons/faHourglassEnd"; +export { definition as faHourglassHalf } from "@fortawesome/free-solid-svg-icons/faHourglassHalf"; +export { definition as faHourglassStart } from "@fortawesome/free-solid-svg-icons/faHourglassStart"; +export { definition as faHouse } from "@fortawesome/free-solid-svg-icons/faHouse"; +export { definition as faHouseChimney } from "@fortawesome/free-solid-svg-icons/faHouseChimney"; +export { definition as faHouseChimneyCrack } from "@fortawesome/free-solid-svg-icons/faHouseChimneyCrack"; +export { definition as faHouseChimneyMedical } from "@fortawesome/free-solid-svg-icons/faHouseChimneyMedical"; +export { definition as faHouseChimneyUser } from "@fortawesome/free-solid-svg-icons/faHouseChimneyUser"; +export { definition as faHouseChimneyWindow } from "@fortawesome/free-solid-svg-icons/faHouseChimneyWindow"; +export { definition as faHouseCircleCheck } from "@fortawesome/free-solid-svg-icons/faHouseCircleCheck"; +export { definition as faHouseCircleExclamation } from "@fortawesome/free-solid-svg-icons/faHouseCircleExclamation"; +export { definition as faHouseCircleXmark } from "@fortawesome/free-solid-svg-icons/faHouseCircleXmark"; +export { definition as faHouseCrack } from "@fortawesome/free-solid-svg-icons/faHouseCrack"; +export { definition as faHouseDamage } from "@fortawesome/free-solid-svg-icons/faHouseDamage"; +export { definition as faHouseFire } from "@fortawesome/free-solid-svg-icons/faHouseFire"; +export { definition as faHouseFlag } from "@fortawesome/free-solid-svg-icons/faHouseFlag"; +export { definition as faHouseFloodWater } from "@fortawesome/free-solid-svg-icons/faHouseFloodWater"; +export { definition as faHouseFloodWaterCircleArrowRight } from "@fortawesome/free-solid-svg-icons/faHouseFloodWaterCircleArrowRight"; +export { definition as faHouseLaptop } from "@fortawesome/free-solid-svg-icons/faHouseLaptop"; +export { definition as faHouseLock } from "@fortawesome/free-solid-svg-icons/faHouseLock"; +export { definition as faHouseMedical } from "@fortawesome/free-solid-svg-icons/faHouseMedical"; +export { definition as faHouseMedicalCircleCheck } from "@fortawesome/free-solid-svg-icons/faHouseMedicalCircleCheck"; +export { definition as faHouseMedicalCircleExclamation } from "@fortawesome/free-solid-svg-icons/faHouseMedicalCircleExclamation"; +export { definition as faHouseMedicalCircleXmark } from "@fortawesome/free-solid-svg-icons/faHouseMedicalCircleXmark"; +export { definition as faHouseMedicalFlag } from "@fortawesome/free-solid-svg-icons/faHouseMedicalFlag"; +export { definition as faHouseSignal } from "@fortawesome/free-solid-svg-icons/faHouseSignal"; +export { definition as faHouseTsunami } from "@fortawesome/free-solid-svg-icons/faHouseTsunami"; +export { definition as faHouseUser } from "@fortawesome/free-solid-svg-icons/faHouseUser"; +export { definition as faHryvnia } from "@fortawesome/free-solid-svg-icons/faHryvnia"; +export { definition as faHryvniaSign } from "@fortawesome/free-solid-svg-icons/faHryvniaSign"; +export { definition as faHurricane } from "@fortawesome/free-solid-svg-icons/faHurricane"; +export { definition as faI } from "@fortawesome/free-solid-svg-icons/faI"; +export { definition as faICursor } from "@fortawesome/free-solid-svg-icons/faICursor"; +export { definition as faIceCream } from "@fortawesome/free-solid-svg-icons/faIceCream"; +export { definition as faIcicles } from "@fortawesome/free-solid-svg-icons/faIcicles"; +export { definition as faIcons } from "@fortawesome/free-solid-svg-icons/faIcons"; +export { definition as faIdBadge } from "@fortawesome/free-solid-svg-icons/faIdBadge"; +export { definition as faIdCard } from "@fortawesome/free-solid-svg-icons/faIdCard"; +export { definition as faIdCardAlt } from "@fortawesome/free-solid-svg-icons/faIdCardAlt"; +export { definition as faIdCardClip } from "@fortawesome/free-solid-svg-icons/faIdCardClip"; +export { definition as faIgloo } from "@fortawesome/free-solid-svg-icons/faIgloo"; +export { definition as faIls } from "@fortawesome/free-solid-svg-icons/faIls"; +export { definition as faImage } from "@fortawesome/free-solid-svg-icons/faImage"; +export { definition as faImagePortrait } from "@fortawesome/free-solid-svg-icons/faImagePortrait"; +export { definition as faImages } from "@fortawesome/free-solid-svg-icons/faImages"; +export { definition as faInbox } from "@fortawesome/free-solid-svg-icons/faInbox"; +export { definition as faIndent } from "@fortawesome/free-solid-svg-icons/faIndent"; +export { definition as faIndianRupee } from "@fortawesome/free-solid-svg-icons/faIndianRupee"; +export { definition as faIndianRupeeSign } from "@fortawesome/free-solid-svg-icons/faIndianRupeeSign"; +export { definition as faIndustry } from "@fortawesome/free-solid-svg-icons/faIndustry"; +export { definition as faInfinity } from "@fortawesome/free-solid-svg-icons/faInfinity"; +export { definition as faInfo } from "@fortawesome/free-solid-svg-icons/faInfo"; +export { definition as faInfoCircle } from "@fortawesome/free-solid-svg-icons/faInfoCircle"; +export { definition as faInr } from "@fortawesome/free-solid-svg-icons/faInr"; +export { definition as faInstitution } from "@fortawesome/free-solid-svg-icons/faInstitution"; +export { definition as faItalic } from "@fortawesome/free-solid-svg-icons/faItalic"; +export { definition as faJ } from "@fortawesome/free-solid-svg-icons/faJ"; +export { definition as faJar } from "@fortawesome/free-solid-svg-icons/faJar"; +export { definition as faJarWheat } from "@fortawesome/free-solid-svg-icons/faJarWheat"; +export { definition as faJedi } from "@fortawesome/free-solid-svg-icons/faJedi"; +export { definition as faJetFighter } from "@fortawesome/free-solid-svg-icons/faJetFighter"; +export { definition as faJetFighterUp } from "@fortawesome/free-solid-svg-icons/faJetFighterUp"; +export { definition as faJoint } from "@fortawesome/free-solid-svg-icons/faJoint"; +export { definition as faJournalWhills } from "@fortawesome/free-solid-svg-icons/faJournalWhills"; +export { definition as faJpy } from "@fortawesome/free-solid-svg-icons/faJpy"; +export { definition as faJugDetergent } from "@fortawesome/free-solid-svg-icons/faJugDetergent"; +export { definition as faK } from "@fortawesome/free-solid-svg-icons/faK"; +export { definition as faKaaba } from "@fortawesome/free-solid-svg-icons/faKaaba"; +export { definition as faKey } from "@fortawesome/free-solid-svg-icons/faKey"; +export { definition as faKeyboard } from "@fortawesome/free-solid-svg-icons/faKeyboard"; +export { definition as faKhanda } from "@fortawesome/free-solid-svg-icons/faKhanda"; +export { definition as faKipSign } from "@fortawesome/free-solid-svg-icons/faKipSign"; +export { definition as faKiss } from "@fortawesome/free-solid-svg-icons/faKiss"; +export { definition as faKissBeam } from "@fortawesome/free-solid-svg-icons/faKissBeam"; +export { definition as faKissWinkHeart } from "@fortawesome/free-solid-svg-icons/faKissWinkHeart"; +export { definition as faKitMedical } from "@fortawesome/free-solid-svg-icons/faKitMedical"; +export { definition as faKitchenSet } from "@fortawesome/free-solid-svg-icons/faKitchenSet"; +export { definition as faKiwiBird } from "@fortawesome/free-solid-svg-icons/faKiwiBird"; +export { definition as faKrw } from "@fortawesome/free-solid-svg-icons/faKrw"; +export { definition as faL } from "@fortawesome/free-solid-svg-icons/faL"; +export { definition as faLadderWater } from "@fortawesome/free-solid-svg-icons/faLadderWater"; +export { definition as faLandMineOn } from "@fortawesome/free-solid-svg-icons/faLandMineOn"; +export { definition as faLandmark } from "@fortawesome/free-solid-svg-icons/faLandmark"; +export { definition as faLandmarkAlt } from "@fortawesome/free-solid-svg-icons/faLandmarkAlt"; +export { definition as faLandmarkDome } from "@fortawesome/free-solid-svg-icons/faLandmarkDome"; +export { definition as faLandmarkFlag } from "@fortawesome/free-solid-svg-icons/faLandmarkFlag"; +export { definition as faLanguage } from "@fortawesome/free-solid-svg-icons/faLanguage"; +export { definition as faLaptop } from "@fortawesome/free-solid-svg-icons/faLaptop"; +export { definition as faLaptopCode } from "@fortawesome/free-solid-svg-icons/faLaptopCode"; +export { definition as faLaptopFile } from "@fortawesome/free-solid-svg-icons/faLaptopFile"; +export { definition as faLaptopHouse } from "@fortawesome/free-solid-svg-icons/faLaptopHouse"; +export { definition as faLaptopMedical } from "@fortawesome/free-solid-svg-icons/faLaptopMedical"; +export { definition as faLariSign } from "@fortawesome/free-solid-svg-icons/faLariSign"; +export { definition as faLaugh } from "@fortawesome/free-solid-svg-icons/faLaugh"; +export { definition as faLaughBeam } from "@fortawesome/free-solid-svg-icons/faLaughBeam"; +export { definition as faLaughSquint } from "@fortawesome/free-solid-svg-icons/faLaughSquint"; +export { definition as faLaughWink } from "@fortawesome/free-solid-svg-icons/faLaughWink"; +export { definition as faLayerGroup } from "@fortawesome/free-solid-svg-icons/faLayerGroup"; +export { definition as faLeaf } from "@fortawesome/free-solid-svg-icons/faLeaf"; +export { definition as faLeftLong } from "@fortawesome/free-solid-svg-icons/faLeftLong"; +export { definition as faLeftRight } from "@fortawesome/free-solid-svg-icons/faLeftRight"; +export { definition as faLegal } from "@fortawesome/free-solid-svg-icons/faLegal"; +export { definition as faLemon } from "@fortawesome/free-solid-svg-icons/faLemon"; +export { definition as faLessThan } from "@fortawesome/free-solid-svg-icons/faLessThan"; +export { definition as faLessThanEqual } from "@fortawesome/free-solid-svg-icons/faLessThanEqual"; +export { definition as faLevelDown } from "@fortawesome/free-solid-svg-icons/faLevelDown"; +export { definition as faLevelDownAlt } from "@fortawesome/free-solid-svg-icons/faLevelDownAlt"; +export { definition as faLevelUp } from "@fortawesome/free-solid-svg-icons/faLevelUp"; +export { definition as faLevelUpAlt } from "@fortawesome/free-solid-svg-icons/faLevelUpAlt"; +export { definition as faLifeRing } from "@fortawesome/free-solid-svg-icons/faLifeRing"; +export { definition as faLightbulb } from "@fortawesome/free-solid-svg-icons/faLightbulb"; +export { definition as faLineChart } from "@fortawesome/free-solid-svg-icons/faLineChart"; +export { definition as faLinesLeaning } from "@fortawesome/free-solid-svg-icons/faLinesLeaning"; +export { definition as faLink } from "@fortawesome/free-solid-svg-icons/faLink"; +export { definition as faLinkSlash } from "@fortawesome/free-solid-svg-icons/faLinkSlash"; +export { definition as faLiraSign } from "@fortawesome/free-solid-svg-icons/faLiraSign"; +export { definition as faList } from "@fortawesome/free-solid-svg-icons/faList"; +export { definition as faList12 } from "@fortawesome/free-solid-svg-icons/faList12"; +export { definition as faListAlt } from "@fortawesome/free-solid-svg-icons/faListAlt"; +export { definition as faListCheck } from "@fortawesome/free-solid-svg-icons/faListCheck"; +export { definition as faListDots } from "@fortawesome/free-solid-svg-icons/faListDots"; +export { definition as faListNumeric } from "@fortawesome/free-solid-svg-icons/faListNumeric"; +export { definition as faListOl } from "@fortawesome/free-solid-svg-icons/faListOl"; +export { definition as faListSquares } from "@fortawesome/free-solid-svg-icons/faListSquares"; +export { definition as faListUl } from "@fortawesome/free-solid-svg-icons/faListUl"; +export { definition as faLitecoinSign } from "@fortawesome/free-solid-svg-icons/faLitecoinSign"; +export { definition as faLocation } from "@fortawesome/free-solid-svg-icons/faLocation"; +export { definition as faLocationArrow } from "@fortawesome/free-solid-svg-icons/faLocationArrow"; +export { definition as faLocationCrosshairs } from "@fortawesome/free-solid-svg-icons/faLocationCrosshairs"; +export { definition as faLocationDot } from "@fortawesome/free-solid-svg-icons/faLocationDot"; +export { definition as faLocationPin } from "@fortawesome/free-solid-svg-icons/faLocationPin"; +export { definition as faLocationPinLock } from "@fortawesome/free-solid-svg-icons/faLocationPinLock"; +export { definition as faLock } from "@fortawesome/free-solid-svg-icons/faLock"; +export { definition as faLockOpen } from "@fortawesome/free-solid-svg-icons/faLockOpen"; +export { definition as faLocust } from "@fortawesome/free-solid-svg-icons/faLocust"; +export { definition as faLongArrowAltDown } from "@fortawesome/free-solid-svg-icons/faLongArrowAltDown"; +export { definition as faLongArrowAltLeft } from "@fortawesome/free-solid-svg-icons/faLongArrowAltLeft"; +export { definition as faLongArrowAltRight } from "@fortawesome/free-solid-svg-icons/faLongArrowAltRight"; +export { definition as faLongArrowAltUp } from "@fortawesome/free-solid-svg-icons/faLongArrowAltUp"; +export { definition as faLongArrowDown } from "@fortawesome/free-solid-svg-icons/faLongArrowDown"; +export { definition as faLongArrowLeft } from "@fortawesome/free-solid-svg-icons/faLongArrowLeft"; +export { definition as faLongArrowRight } from "@fortawesome/free-solid-svg-icons/faLongArrowRight"; +export { definition as faLongArrowUp } from "@fortawesome/free-solid-svg-icons/faLongArrowUp"; +export { definition as faLowVision } from "@fortawesome/free-solid-svg-icons/faLowVision"; +export { definition as faLuggageCart } from "@fortawesome/free-solid-svg-icons/faLuggageCart"; +export { definition as faLungs } from "@fortawesome/free-solid-svg-icons/faLungs"; +export { definition as faLungsVirus } from "@fortawesome/free-solid-svg-icons/faLungsVirus"; +export { definition as faM } from "@fortawesome/free-solid-svg-icons/faM"; +export { definition as faMagic } from "@fortawesome/free-solid-svg-icons/faMagic"; +export { definition as faMagicWandSparkles } from "@fortawesome/free-solid-svg-icons/faMagicWandSparkles"; +export { definition as faMagnet } from "@fortawesome/free-solid-svg-icons/faMagnet"; +export { definition as faMagnifyingGlass } from "@fortawesome/free-solid-svg-icons/faMagnifyingGlass"; +export { definition as faMagnifyingGlassArrowRight } from "@fortawesome/free-solid-svg-icons/faMagnifyingGlassArrowRight"; +export { definition as faMagnifyingGlassChart } from "@fortawesome/free-solid-svg-icons/faMagnifyingGlassChart"; +export { definition as faMagnifyingGlassDollar } from "@fortawesome/free-solid-svg-icons/faMagnifyingGlassDollar"; +export { definition as faMagnifyingGlassLocation } from "@fortawesome/free-solid-svg-icons/faMagnifyingGlassLocation"; +export { definition as faMagnifyingGlassMinus } from "@fortawesome/free-solid-svg-icons/faMagnifyingGlassMinus"; +export { definition as faMagnifyingGlassPlus } from "@fortawesome/free-solid-svg-icons/faMagnifyingGlassPlus"; +export { definition as faMailBulk } from "@fortawesome/free-solid-svg-icons/faMailBulk"; +export { definition as faMailForward } from "@fortawesome/free-solid-svg-icons/faMailForward"; +export { definition as faMailReply } from "@fortawesome/free-solid-svg-icons/faMailReply"; +export { definition as faMailReplyAll } from "@fortawesome/free-solid-svg-icons/faMailReplyAll"; +export { definition as faMale } from "@fortawesome/free-solid-svg-icons/faMale"; +export { definition as faManatSign } from "@fortawesome/free-solid-svg-icons/faManatSign"; +export { definition as faMap } from "@fortawesome/free-solid-svg-icons/faMap"; +export { definition as faMapLocation } from "@fortawesome/free-solid-svg-icons/faMapLocation"; +export { definition as faMapLocationDot } from "@fortawesome/free-solid-svg-icons/faMapLocationDot"; +export { definition as faMapMarked } from "@fortawesome/free-solid-svg-icons/faMapMarked"; +export { definition as faMapMarkedAlt } from "@fortawesome/free-solid-svg-icons/faMapMarkedAlt"; +export { definition as faMapMarker } from "@fortawesome/free-solid-svg-icons/faMapMarker"; +export { definition as faMapMarkerAlt } from "@fortawesome/free-solid-svg-icons/faMapMarkerAlt"; +export { definition as faMapPin } from "@fortawesome/free-solid-svg-icons/faMapPin"; +export { definition as faMapSigns } from "@fortawesome/free-solid-svg-icons/faMapSigns"; +export { definition as faMarker } from "@fortawesome/free-solid-svg-icons/faMarker"; +export { definition as faMars } from "@fortawesome/free-solid-svg-icons/faMars"; +export { definition as faMarsAndVenus } from "@fortawesome/free-solid-svg-icons/faMarsAndVenus"; +export { definition as faMarsAndVenusBurst } from "@fortawesome/free-solid-svg-icons/faMarsAndVenusBurst"; +export { definition as faMarsDouble } from "@fortawesome/free-solid-svg-icons/faMarsDouble"; +export { definition as faMarsStroke } from "@fortawesome/free-solid-svg-icons/faMarsStroke"; +export { definition as faMarsStrokeH } from "@fortawesome/free-solid-svg-icons/faMarsStrokeH"; +export { definition as faMarsStrokeRight } from "@fortawesome/free-solid-svg-icons/faMarsStrokeRight"; +export { definition as faMarsStrokeUp } from "@fortawesome/free-solid-svg-icons/faMarsStrokeUp"; +export { definition as faMarsStrokeV } from "@fortawesome/free-solid-svg-icons/faMarsStrokeV"; +export { definition as faMartiniGlass } from "@fortawesome/free-solid-svg-icons/faMartiniGlass"; +export { definition as faMartiniGlassCitrus } from "@fortawesome/free-solid-svg-icons/faMartiniGlassCitrus"; +export { definition as faMartiniGlassEmpty } from "@fortawesome/free-solid-svg-icons/faMartiniGlassEmpty"; +export { definition as faMask } from "@fortawesome/free-solid-svg-icons/faMask"; +export { definition as faMaskFace } from "@fortawesome/free-solid-svg-icons/faMaskFace"; +export { definition as faMaskVentilator } from "@fortawesome/free-solid-svg-icons/faMaskVentilator"; +export { definition as faMasksTheater } from "@fortawesome/free-solid-svg-icons/faMasksTheater"; +export { definition as faMattressPillow } from "@fortawesome/free-solid-svg-icons/faMattressPillow"; +export { definition as faMaximize } from "@fortawesome/free-solid-svg-icons/faMaximize"; +export { definition as faMedal } from "@fortawesome/free-solid-svg-icons/faMedal"; +export { definition as faMedkit } from "@fortawesome/free-solid-svg-icons/faMedkit"; +export { definition as faMeh } from "@fortawesome/free-solid-svg-icons/faMeh"; +export { definition as faMehBlank } from "@fortawesome/free-solid-svg-icons/faMehBlank"; +export { definition as faMehRollingEyes } from "@fortawesome/free-solid-svg-icons/faMehRollingEyes"; +export { definition as faMemory } from "@fortawesome/free-solid-svg-icons/faMemory"; +export { definition as faMenorah } from "@fortawesome/free-solid-svg-icons/faMenorah"; +export { definition as faMercury } from "@fortawesome/free-solid-svg-icons/faMercury"; +export { definition as faMessage } from "@fortawesome/free-solid-svg-icons/faMessage"; +export { definition as faMeteor } from "@fortawesome/free-solid-svg-icons/faMeteor"; +export { definition as faMicrochip } from "@fortawesome/free-solid-svg-icons/faMicrochip"; +export { definition as faMicrophone } from "@fortawesome/free-solid-svg-icons/faMicrophone"; +export { definition as faMicrophoneAlt } from "@fortawesome/free-solid-svg-icons/faMicrophoneAlt"; +export { definition as faMicrophoneAltSlash } from "@fortawesome/free-solid-svg-icons/faMicrophoneAltSlash"; +export { definition as faMicrophoneLines } from "@fortawesome/free-solid-svg-icons/faMicrophoneLines"; +export { definition as faMicrophoneLinesSlash } from "@fortawesome/free-solid-svg-icons/faMicrophoneLinesSlash"; +export { definition as faMicrophoneSlash } from "@fortawesome/free-solid-svg-icons/faMicrophoneSlash"; +export { definition as faMicroscope } from "@fortawesome/free-solid-svg-icons/faMicroscope"; +export { definition as faMillSign } from "@fortawesome/free-solid-svg-icons/faMillSign"; +export { definition as faMinimize } from "@fortawesome/free-solid-svg-icons/faMinimize"; +export { definition as faMinus } from "@fortawesome/free-solid-svg-icons/faMinus"; +export { definition as faMinusCircle } from "@fortawesome/free-solid-svg-icons/faMinusCircle"; +export { definition as faMinusSquare } from "@fortawesome/free-solid-svg-icons/faMinusSquare"; +export { definition as faMitten } from "@fortawesome/free-solid-svg-icons/faMitten"; +export { definition as faMobile } from "@fortawesome/free-solid-svg-icons/faMobile"; +export { definition as faMobileAlt } from "@fortawesome/free-solid-svg-icons/faMobileAlt"; +export { definition as faMobileAndroid } from "@fortawesome/free-solid-svg-icons/faMobileAndroid"; +export { definition as faMobileAndroidAlt } from "@fortawesome/free-solid-svg-icons/faMobileAndroidAlt"; +export { definition as faMobileButton } from "@fortawesome/free-solid-svg-icons/faMobileButton"; +export { definition as faMobilePhone } from "@fortawesome/free-solid-svg-icons/faMobilePhone"; +export { definition as faMobileRetro } from "@fortawesome/free-solid-svg-icons/faMobileRetro"; +export { definition as faMobileScreen } from "@fortawesome/free-solid-svg-icons/faMobileScreen"; +export { definition as faMobileScreenButton } from "@fortawesome/free-solid-svg-icons/faMobileScreenButton"; +export { definition as faMoneyBill } from "@fortawesome/free-solid-svg-icons/faMoneyBill"; +export { definition as faMoneyBill1 } from "@fortawesome/free-solid-svg-icons/faMoneyBill1"; +export { definition as faMoneyBill1Wave } from "@fortawesome/free-solid-svg-icons/faMoneyBill1Wave"; +export { definition as faMoneyBillAlt } from "@fortawesome/free-solid-svg-icons/faMoneyBillAlt"; +export { definition as faMoneyBillTransfer } from "@fortawesome/free-solid-svg-icons/faMoneyBillTransfer"; +export { definition as faMoneyBillTrendUp } from "@fortawesome/free-solid-svg-icons/faMoneyBillTrendUp"; +export { definition as faMoneyBillWave } from "@fortawesome/free-solid-svg-icons/faMoneyBillWave"; +export { definition as faMoneyBillWaveAlt } from "@fortawesome/free-solid-svg-icons/faMoneyBillWaveAlt"; +export { definition as faMoneyBillWheat } from "@fortawesome/free-solid-svg-icons/faMoneyBillWheat"; +export { definition as faMoneyBills } from "@fortawesome/free-solid-svg-icons/faMoneyBills"; +export { definition as faMoneyCheck } from "@fortawesome/free-solid-svg-icons/faMoneyCheck"; +export { definition as faMoneyCheckAlt } from "@fortawesome/free-solid-svg-icons/faMoneyCheckAlt"; +export { definition as faMoneyCheckDollar } from "@fortawesome/free-solid-svg-icons/faMoneyCheckDollar"; +export { definition as faMonument } from "@fortawesome/free-solid-svg-icons/faMonument"; +export { definition as faMoon } from "@fortawesome/free-solid-svg-icons/faMoon"; +export { definition as faMortarBoard } from "@fortawesome/free-solid-svg-icons/faMortarBoard"; +export { definition as faMortarPestle } from "@fortawesome/free-solid-svg-icons/faMortarPestle"; +export { definition as faMosque } from "@fortawesome/free-solid-svg-icons/faMosque"; +export { definition as faMosquito } from "@fortawesome/free-solid-svg-icons/faMosquito"; +export { definition as faMosquitoNet } from "@fortawesome/free-solid-svg-icons/faMosquitoNet"; +export { definition as faMotorcycle } from "@fortawesome/free-solid-svg-icons/faMotorcycle"; +export { definition as faMound } from "@fortawesome/free-solid-svg-icons/faMound"; +export { definition as faMountain } from "@fortawesome/free-solid-svg-icons/faMountain"; +export { definition as faMountainCity } from "@fortawesome/free-solid-svg-icons/faMountainCity"; +export { definition as faMountainSun } from "@fortawesome/free-solid-svg-icons/faMountainSun"; +export { definition as faMouse } from "@fortawesome/free-solid-svg-icons/faMouse"; +export { definition as faMousePointer } from "@fortawesome/free-solid-svg-icons/faMousePointer"; +export { definition as faMugHot } from "@fortawesome/free-solid-svg-icons/faMugHot"; +export { definition as faMugSaucer } from "@fortawesome/free-solid-svg-icons/faMugSaucer"; +export { definition as faMultiply } from "@fortawesome/free-solid-svg-icons/faMultiply"; +export { definition as faMuseum } from "@fortawesome/free-solid-svg-icons/faMuseum"; +export { definition as faMusic } from "@fortawesome/free-solid-svg-icons/faMusic"; +export { definition as faN } from "@fortawesome/free-solid-svg-icons/faN"; +export { definition as faNairaSign } from "@fortawesome/free-solid-svg-icons/faNairaSign"; +export { definition as faNavicon } from "@fortawesome/free-solid-svg-icons/faNavicon"; +export { definition as faNetworkWired } from "@fortawesome/free-solid-svg-icons/faNetworkWired"; +export { definition as faNeuter } from "@fortawesome/free-solid-svg-icons/faNeuter"; +export { definition as faNewspaper } from "@fortawesome/free-solid-svg-icons/faNewspaper"; +export { definition as faNotEqual } from "@fortawesome/free-solid-svg-icons/faNotEqual"; +export { definition as faNotdef } from "@fortawesome/free-solid-svg-icons/faNotdef"; +export { definition as faNoteSticky } from "@fortawesome/free-solid-svg-icons/faNoteSticky"; +export { definition as faNotesMedical } from "@fortawesome/free-solid-svg-icons/faNotesMedical"; +export { definition as faO } from "@fortawesome/free-solid-svg-icons/faO"; +export { definition as faObjectGroup } from "@fortawesome/free-solid-svg-icons/faObjectGroup"; +export { definition as faObjectUngroup } from "@fortawesome/free-solid-svg-icons/faObjectUngroup"; +export { definition as faOilCan } from "@fortawesome/free-solid-svg-icons/faOilCan"; +export { definition as faOilWell } from "@fortawesome/free-solid-svg-icons/faOilWell"; +export { definition as faOm } from "@fortawesome/free-solid-svg-icons/faOm"; +export { definition as faOtter } from "@fortawesome/free-solid-svg-icons/faOtter"; +export { definition as faOutdent } from "@fortawesome/free-solid-svg-icons/faOutdent"; +export { definition as faP } from "@fortawesome/free-solid-svg-icons/faP"; +export { definition as faPager } from "@fortawesome/free-solid-svg-icons/faPager"; +export { definition as faPaintRoller } from "@fortawesome/free-solid-svg-icons/faPaintRoller"; +export { definition as faPaintbrush } from "@fortawesome/free-solid-svg-icons/faPaintbrush"; +export { definition as faPalette } from "@fortawesome/free-solid-svg-icons/faPalette"; +export { definition as faPallet } from "@fortawesome/free-solid-svg-icons/faPallet"; +export { definition as faPanorama } from "@fortawesome/free-solid-svg-icons/faPanorama"; +export { definition as faPaperPlane } from "@fortawesome/free-solid-svg-icons/faPaperPlane"; +export { definition as faPaperclip } from "@fortawesome/free-solid-svg-icons/faPaperclip"; +export { definition as faParachuteBox } from "@fortawesome/free-solid-svg-icons/faParachuteBox"; +export { definition as faParagraph } from "@fortawesome/free-solid-svg-icons/faParagraph"; +export { definition as faParking } from "@fortawesome/free-solid-svg-icons/faParking"; +export { definition as faPassport } from "@fortawesome/free-solid-svg-icons/faPassport"; +export { definition as faPastafarianism } from "@fortawesome/free-solid-svg-icons/faPastafarianism"; +export { definition as faPaste } from "@fortawesome/free-solid-svg-icons/faPaste"; +export { definition as faPause } from "@fortawesome/free-solid-svg-icons/faPause"; +export { definition as faPauseCircle } from "@fortawesome/free-solid-svg-icons/faPauseCircle"; +export { definition as faPaw } from "@fortawesome/free-solid-svg-icons/faPaw"; +export { definition as faPeace } from "@fortawesome/free-solid-svg-icons/faPeace"; +export { definition as faPen } from "@fortawesome/free-solid-svg-icons/faPen"; +export { definition as faPenAlt } from "@fortawesome/free-solid-svg-icons/faPenAlt"; +export { definition as faPenClip } from "@fortawesome/free-solid-svg-icons/faPenClip"; +export { definition as faPenFancy } from "@fortawesome/free-solid-svg-icons/faPenFancy"; +export { definition as faPenNib } from "@fortawesome/free-solid-svg-icons/faPenNib"; +export { definition as faPenRuler } from "@fortawesome/free-solid-svg-icons/faPenRuler"; +export { definition as faPenSquare } from "@fortawesome/free-solid-svg-icons/faPenSquare"; +export { definition as faPenToSquare } from "@fortawesome/free-solid-svg-icons/faPenToSquare"; +export { definition as faPencil } from "@fortawesome/free-solid-svg-icons/faPencil"; +export { definition as faPencilAlt } from "@fortawesome/free-solid-svg-icons/faPencilAlt"; +export { definition as faPencilRuler } from "@fortawesome/free-solid-svg-icons/faPencilRuler"; +export { definition as faPencilSquare } from "@fortawesome/free-solid-svg-icons/faPencilSquare"; +export { definition as faPeopleArrows } from "@fortawesome/free-solid-svg-icons/faPeopleArrows"; +export { definition as faPeopleArrowsLeftRight } from "@fortawesome/free-solid-svg-icons/faPeopleArrowsLeftRight"; +export { definition as faPeopleCarry } from "@fortawesome/free-solid-svg-icons/faPeopleCarry"; +export { definition as faPeopleCarryBox } from "@fortawesome/free-solid-svg-icons/faPeopleCarryBox"; +export { definition as faPeopleGroup } from "@fortawesome/free-solid-svg-icons/faPeopleGroup"; +export { definition as faPeopleLine } from "@fortawesome/free-solid-svg-icons/faPeopleLine"; +export { definition as faPeoplePulling } from "@fortawesome/free-solid-svg-icons/faPeoplePulling"; +export { definition as faPeopleRobbery } from "@fortawesome/free-solid-svg-icons/faPeopleRobbery"; +export { definition as faPeopleRoof } from "@fortawesome/free-solid-svg-icons/faPeopleRoof"; +export { definition as faPepperHot } from "@fortawesome/free-solid-svg-icons/faPepperHot"; +export { definition as faPercent } from "@fortawesome/free-solid-svg-icons/faPercent"; +export { definition as faPercentage } from "@fortawesome/free-solid-svg-icons/faPercentage"; +export { definition as faPerson } from "@fortawesome/free-solid-svg-icons/faPerson"; +export { definition as faPersonArrowDownToLine } from "@fortawesome/free-solid-svg-icons/faPersonArrowDownToLine"; +export { definition as faPersonArrowUpFromLine } from "@fortawesome/free-solid-svg-icons/faPersonArrowUpFromLine"; +export { definition as faPersonBiking } from "@fortawesome/free-solid-svg-icons/faPersonBiking"; +export { definition as faPersonBooth } from "@fortawesome/free-solid-svg-icons/faPersonBooth"; +export { definition as faPersonBreastfeeding } from "@fortawesome/free-solid-svg-icons/faPersonBreastfeeding"; +export { definition as faPersonBurst } from "@fortawesome/free-solid-svg-icons/faPersonBurst"; +export { definition as faPersonCane } from "@fortawesome/free-solid-svg-icons/faPersonCane"; +export { definition as faPersonChalkboard } from "@fortawesome/free-solid-svg-icons/faPersonChalkboard"; +export { definition as faPersonCircleCheck } from "@fortawesome/free-solid-svg-icons/faPersonCircleCheck"; +export { definition as faPersonCircleExclamation } from "@fortawesome/free-solid-svg-icons/faPersonCircleExclamation"; +export { definition as faPersonCircleMinus } from "@fortawesome/free-solid-svg-icons/faPersonCircleMinus"; +export { definition as faPersonCirclePlus } from "@fortawesome/free-solid-svg-icons/faPersonCirclePlus"; +export { definition as faPersonCircleQuestion } from "@fortawesome/free-solid-svg-icons/faPersonCircleQuestion"; +export { definition as faPersonCircleXmark } from "@fortawesome/free-solid-svg-icons/faPersonCircleXmark"; +export { definition as faPersonDigging } from "@fortawesome/free-solid-svg-icons/faPersonDigging"; +export { definition as faPersonDotsFromLine } from "@fortawesome/free-solid-svg-icons/faPersonDotsFromLine"; +export { definition as faPersonDress } from "@fortawesome/free-solid-svg-icons/faPersonDress"; +export { definition as faPersonDressBurst } from "@fortawesome/free-solid-svg-icons/faPersonDressBurst"; +export { definition as faPersonDrowning } from "@fortawesome/free-solid-svg-icons/faPersonDrowning"; +export { definition as faPersonFalling } from "@fortawesome/free-solid-svg-icons/faPersonFalling"; +export { definition as faPersonFallingBurst } from "@fortawesome/free-solid-svg-icons/faPersonFallingBurst"; +export { definition as faPersonHalfDress } from "@fortawesome/free-solid-svg-icons/faPersonHalfDress"; +export { definition as faPersonHarassing } from "@fortawesome/free-solid-svg-icons/faPersonHarassing"; +export { definition as faPersonHiking } from "@fortawesome/free-solid-svg-icons/faPersonHiking"; +export { definition as faPersonMilitaryPointing } from "@fortawesome/free-solid-svg-icons/faPersonMilitaryPointing"; +export { definition as faPersonMilitaryRifle } from "@fortawesome/free-solid-svg-icons/faPersonMilitaryRifle"; +export { definition as faPersonMilitaryToPerson } from "@fortawesome/free-solid-svg-icons/faPersonMilitaryToPerson"; +export { definition as faPersonPraying } from "@fortawesome/free-solid-svg-icons/faPersonPraying"; +export { definition as faPersonPregnant } from "@fortawesome/free-solid-svg-icons/faPersonPregnant"; +export { definition as faPersonRays } from "@fortawesome/free-solid-svg-icons/faPersonRays"; +export { definition as faPersonRifle } from "@fortawesome/free-solid-svg-icons/faPersonRifle"; +export { definition as faPersonRunning } from "@fortawesome/free-solid-svg-icons/faPersonRunning"; +export { definition as faPersonShelter } from "@fortawesome/free-solid-svg-icons/faPersonShelter"; +export { definition as faPersonSkating } from "@fortawesome/free-solid-svg-icons/faPersonSkating"; +export { definition as faPersonSkiing } from "@fortawesome/free-solid-svg-icons/faPersonSkiing"; +export { definition as faPersonSkiingNordic } from "@fortawesome/free-solid-svg-icons/faPersonSkiingNordic"; +export { definition as faPersonSnowboarding } from "@fortawesome/free-solid-svg-icons/faPersonSnowboarding"; +export { definition as faPersonSwimming } from "@fortawesome/free-solid-svg-icons/faPersonSwimming"; +export { definition as faPersonThroughWindow } from "@fortawesome/free-solid-svg-icons/faPersonThroughWindow"; +export { definition as faPersonWalking } from "@fortawesome/free-solid-svg-icons/faPersonWalking"; +export { definition as faPersonWalkingArrowLoopLeft } from "@fortawesome/free-solid-svg-icons/faPersonWalkingArrowLoopLeft"; +export { definition as faPersonWalkingArrowRight } from "@fortawesome/free-solid-svg-icons/faPersonWalkingArrowRight"; +export { definition as faPersonWalkingDashedLineArrowRight } from "@fortawesome/free-solid-svg-icons/faPersonWalkingDashedLineArrowRight"; +export { definition as faPersonWalkingLuggage } from "@fortawesome/free-solid-svg-icons/faPersonWalkingLuggage"; +export { definition as faPersonWalkingWithCane } from "@fortawesome/free-solid-svg-icons/faPersonWalkingWithCane"; +export { definition as faPesetaSign } from "@fortawesome/free-solid-svg-icons/faPesetaSign"; +export { definition as faPesoSign } from "@fortawesome/free-solid-svg-icons/faPesoSign"; +export { definition as faPhone } from "@fortawesome/free-solid-svg-icons/faPhone"; +export { definition as faPhoneAlt } from "@fortawesome/free-solid-svg-icons/faPhoneAlt"; +export { definition as faPhoneFlip } from "@fortawesome/free-solid-svg-icons/faPhoneFlip"; +export { definition as faPhoneSlash } from "@fortawesome/free-solid-svg-icons/faPhoneSlash"; +export { definition as faPhoneSquare } from "@fortawesome/free-solid-svg-icons/faPhoneSquare"; +export { definition as faPhoneSquareAlt } from "@fortawesome/free-solid-svg-icons/faPhoneSquareAlt"; +export { definition as faPhoneVolume } from "@fortawesome/free-solid-svg-icons/faPhoneVolume"; +export { definition as faPhotoFilm } from "@fortawesome/free-solid-svg-icons/faPhotoFilm"; +export { definition as faPhotoVideo } from "@fortawesome/free-solid-svg-icons/faPhotoVideo"; +export { definition as faPieChart } from "@fortawesome/free-solid-svg-icons/faPieChart"; +export { definition as faPiggyBank } from "@fortawesome/free-solid-svg-icons/faPiggyBank"; +export { definition as faPills } from "@fortawesome/free-solid-svg-icons/faPills"; +export { definition as faPingPongPaddleBall } from "@fortawesome/free-solid-svg-icons/faPingPongPaddleBall"; +export { definition as faPizzaSlice } from "@fortawesome/free-solid-svg-icons/faPizzaSlice"; +export { definition as faPlaceOfWorship } from "@fortawesome/free-solid-svg-icons/faPlaceOfWorship"; +export { definition as faPlane } from "@fortawesome/free-solid-svg-icons/faPlane"; +export { definition as faPlaneArrival } from "@fortawesome/free-solid-svg-icons/faPlaneArrival"; +export { definition as faPlaneCircleCheck } from "@fortawesome/free-solid-svg-icons/faPlaneCircleCheck"; +export { definition as faPlaneCircleExclamation } from "@fortawesome/free-solid-svg-icons/faPlaneCircleExclamation"; +export { definition as faPlaneCircleXmark } from "@fortawesome/free-solid-svg-icons/faPlaneCircleXmark"; +export { definition as faPlaneDeparture } from "@fortawesome/free-solid-svg-icons/faPlaneDeparture"; +export { definition as faPlaneLock } from "@fortawesome/free-solid-svg-icons/faPlaneLock"; +export { definition as faPlaneSlash } from "@fortawesome/free-solid-svg-icons/faPlaneSlash"; +export { definition as faPlaneUp } from "@fortawesome/free-solid-svg-icons/faPlaneUp"; +export { definition as faPlantWilt } from "@fortawesome/free-solid-svg-icons/faPlantWilt"; +export { definition as faPlateWheat } from "@fortawesome/free-solid-svg-icons/faPlateWheat"; +export { definition as faPlay } from "@fortawesome/free-solid-svg-icons/faPlay"; +export { definition as faPlayCircle } from "@fortawesome/free-solid-svg-icons/faPlayCircle"; +export { definition as faPlug } from "@fortawesome/free-solid-svg-icons/faPlug"; +export { definition as faPlugCircleBolt } from "@fortawesome/free-solid-svg-icons/faPlugCircleBolt"; +export { definition as faPlugCircleCheck } from "@fortawesome/free-solid-svg-icons/faPlugCircleCheck"; +export { definition as faPlugCircleExclamation } from "@fortawesome/free-solid-svg-icons/faPlugCircleExclamation"; +export { definition as faPlugCircleMinus } from "@fortawesome/free-solid-svg-icons/faPlugCircleMinus"; +export { definition as faPlugCirclePlus } from "@fortawesome/free-solid-svg-icons/faPlugCirclePlus"; +export { definition as faPlugCircleXmark } from "@fortawesome/free-solid-svg-icons/faPlugCircleXmark"; +export { definition as faPlus } from "@fortawesome/free-solid-svg-icons/faPlus"; +export { definition as faPlusCircle } from "@fortawesome/free-solid-svg-icons/faPlusCircle"; +export { definition as faPlusMinus } from "@fortawesome/free-solid-svg-icons/faPlusMinus"; +export { definition as faPlusSquare } from "@fortawesome/free-solid-svg-icons/faPlusSquare"; +export { definition as faPodcast } from "@fortawesome/free-solid-svg-icons/faPodcast"; +export { definition as faPoll } from "@fortawesome/free-solid-svg-icons/faPoll"; +export { definition as faPollH } from "@fortawesome/free-solid-svg-icons/faPollH"; +export { definition as faPoo } from "@fortawesome/free-solid-svg-icons/faPoo"; +export { definition as faPooBolt } from "@fortawesome/free-solid-svg-icons/faPooBolt"; +export { definition as faPooStorm } from "@fortawesome/free-solid-svg-icons/faPooStorm"; +export { definition as faPoop } from "@fortawesome/free-solid-svg-icons/faPoop"; +export { definition as faPortrait } from "@fortawesome/free-solid-svg-icons/faPortrait"; +export { definition as faPoundSign } from "@fortawesome/free-solid-svg-icons/faPoundSign"; +export { definition as faPowerOff } from "@fortawesome/free-solid-svg-icons/faPowerOff"; +export { definition as faPray } from "@fortawesome/free-solid-svg-icons/faPray"; +export { definition as faPrayingHands } from "@fortawesome/free-solid-svg-icons/faPrayingHands"; +export { definition as faPrescription } from "@fortawesome/free-solid-svg-icons/faPrescription"; +export { definition as faPrescriptionBottle } from "@fortawesome/free-solid-svg-icons/faPrescriptionBottle"; +export { definition as faPrescriptionBottleAlt } from "@fortawesome/free-solid-svg-icons/faPrescriptionBottleAlt"; +export { definition as faPrescriptionBottleMedical } from "@fortawesome/free-solid-svg-icons/faPrescriptionBottleMedical"; +export { definition as faPrint } from "@fortawesome/free-solid-svg-icons/faPrint"; +export { definition as faProcedures } from "@fortawesome/free-solid-svg-icons/faProcedures"; +export { definition as faProjectDiagram } from "@fortawesome/free-solid-svg-icons/faProjectDiagram"; +export { definition as faPumpMedical } from "@fortawesome/free-solid-svg-icons/faPumpMedical"; +export { definition as faPumpSoap } from "@fortawesome/free-solid-svg-icons/faPumpSoap"; +export { definition as faPuzzlePiece } from "@fortawesome/free-solid-svg-icons/faPuzzlePiece"; +export { definition as faQ } from "@fortawesome/free-solid-svg-icons/faQ"; +export { definition as faQrcode } from "@fortawesome/free-solid-svg-icons/faQrcode"; +export { definition as faQuestion } from "@fortawesome/free-solid-svg-icons/faQuestion"; +export { definition as faQuestionCircle } from "@fortawesome/free-solid-svg-icons/faQuestionCircle"; +export { definition as faQuidditch } from "@fortawesome/free-solid-svg-icons/faQuidditch"; +export { definition as faQuidditchBroomBall } from "@fortawesome/free-solid-svg-icons/faQuidditchBroomBall"; +export { definition as faQuoteLeft } from "@fortawesome/free-solid-svg-icons/faQuoteLeft"; +export { definition as faQuoteLeftAlt } from "@fortawesome/free-solid-svg-icons/faQuoteLeftAlt"; +export { definition as faQuoteRight } from "@fortawesome/free-solid-svg-icons/faQuoteRight"; +export { definition as faQuoteRightAlt } from "@fortawesome/free-solid-svg-icons/faQuoteRightAlt"; +export { definition as faQuran } from "@fortawesome/free-solid-svg-icons/faQuran"; +export { definition as faR } from "@fortawesome/free-solid-svg-icons/faR"; +export { definition as faRadiation } from "@fortawesome/free-solid-svg-icons/faRadiation"; +export { definition as faRadiationAlt } from "@fortawesome/free-solid-svg-icons/faRadiationAlt"; +export { definition as faRadio } from "@fortawesome/free-solid-svg-icons/faRadio"; +export { definition as faRainbow } from "@fortawesome/free-solid-svg-icons/faRainbow"; +export { definition as faRandom } from "@fortawesome/free-solid-svg-icons/faRandom"; +export { definition as faRankingStar } from "@fortawesome/free-solid-svg-icons/faRankingStar"; +export { definition as faReceipt } from "@fortawesome/free-solid-svg-icons/faReceipt"; +export { definition as faRecordVinyl } from "@fortawesome/free-solid-svg-icons/faRecordVinyl"; +export { definition as faRectangleAd } from "@fortawesome/free-solid-svg-icons/faRectangleAd"; +export { definition as faRectangleList } from "@fortawesome/free-solid-svg-icons/faRectangleList"; +export { definition as faRectangleTimes } from "@fortawesome/free-solid-svg-icons/faRectangleTimes"; +export { definition as faRectangleXmark } from "@fortawesome/free-solid-svg-icons/faRectangleXmark"; +export { definition as faRecycle } from "@fortawesome/free-solid-svg-icons/faRecycle"; +export { definition as faRedo } from "@fortawesome/free-solid-svg-icons/faRedo"; +export { definition as faRedoAlt } from "@fortawesome/free-solid-svg-icons/faRedoAlt"; +export { definition as faRefresh } from "@fortawesome/free-solid-svg-icons/faRefresh"; +export { definition as faRegistered } from "@fortawesome/free-solid-svg-icons/faRegistered"; +export { definition as faRemove } from "@fortawesome/free-solid-svg-icons/faRemove"; +export { definition as faRemoveFormat } from "@fortawesome/free-solid-svg-icons/faRemoveFormat"; +export { definition as faReorder } from "@fortawesome/free-solid-svg-icons/faReorder"; +export { definition as faRepeat } from "@fortawesome/free-solid-svg-icons/faRepeat"; +export { definition as faReply } from "@fortawesome/free-solid-svg-icons/faReply"; +export { definition as faReplyAll } from "@fortawesome/free-solid-svg-icons/faReplyAll"; +export { definition as faRepublican } from "@fortawesome/free-solid-svg-icons/faRepublican"; +export { definition as faRestroom } from "@fortawesome/free-solid-svg-icons/faRestroom"; +export { definition as faRetweet } from "@fortawesome/free-solid-svg-icons/faRetweet"; +export { definition as faRibbon } from "@fortawesome/free-solid-svg-icons/faRibbon"; +export { definition as faRightFromBracket } from "@fortawesome/free-solid-svg-icons/faRightFromBracket"; +export { definition as faRightLeft } from "@fortawesome/free-solid-svg-icons/faRightLeft"; +export { definition as faRightLong } from "@fortawesome/free-solid-svg-icons/faRightLong"; +export { definition as faRightToBracket } from "@fortawesome/free-solid-svg-icons/faRightToBracket"; +export { definition as faRing } from "@fortawesome/free-solid-svg-icons/faRing"; +export { definition as faRmb } from "@fortawesome/free-solid-svg-icons/faRmb"; +export { definition as faRoad } from "@fortawesome/free-solid-svg-icons/faRoad"; +export { definition as faRoadBarrier } from "@fortawesome/free-solid-svg-icons/faRoadBarrier"; +export { definition as faRoadBridge } from "@fortawesome/free-solid-svg-icons/faRoadBridge"; +export { definition as faRoadCircleCheck } from "@fortawesome/free-solid-svg-icons/faRoadCircleCheck"; +export { definition as faRoadCircleExclamation } from "@fortawesome/free-solid-svg-icons/faRoadCircleExclamation"; +export { definition as faRoadCircleXmark } from "@fortawesome/free-solid-svg-icons/faRoadCircleXmark"; +export { definition as faRoadLock } from "@fortawesome/free-solid-svg-icons/faRoadLock"; +export { definition as faRoadSpikes } from "@fortawesome/free-solid-svg-icons/faRoadSpikes"; +export { definition as faRobot } from "@fortawesome/free-solid-svg-icons/faRobot"; +export { definition as faRocket } from "@fortawesome/free-solid-svg-icons/faRocket"; +export { definition as faRodAsclepius } from "@fortawesome/free-solid-svg-icons/faRodAsclepius"; +export { definition as faRodSnake } from "@fortawesome/free-solid-svg-icons/faRodSnake"; +export { definition as faRotate } from "@fortawesome/free-solid-svg-icons/faRotate"; +export { definition as faRotateBack } from "@fortawesome/free-solid-svg-icons/faRotateBack"; +export { definition as faRotateBackward } from "@fortawesome/free-solid-svg-icons/faRotateBackward"; +export { definition as faRotateForward } from "@fortawesome/free-solid-svg-icons/faRotateForward"; +export { definition as faRotateLeft } from "@fortawesome/free-solid-svg-icons/faRotateLeft"; +export { definition as faRotateRight } from "@fortawesome/free-solid-svg-icons/faRotateRight"; +export { definition as faRouble } from "@fortawesome/free-solid-svg-icons/faRouble"; +export { definition as faRoute } from "@fortawesome/free-solid-svg-icons/faRoute"; +export { definition as faRss } from "@fortawesome/free-solid-svg-icons/faRss"; +export { definition as faRssSquare } from "@fortawesome/free-solid-svg-icons/faRssSquare"; +export { definition as faRub } from "@fortawesome/free-solid-svg-icons/faRub"; +export { definition as faRuble } from "@fortawesome/free-solid-svg-icons/faRuble"; +export { definition as faRubleSign } from "@fortawesome/free-solid-svg-icons/faRubleSign"; +export { definition as faRug } from "@fortawesome/free-solid-svg-icons/faRug"; +export { definition as faRuler } from "@fortawesome/free-solid-svg-icons/faRuler"; +export { definition as faRulerCombined } from "@fortawesome/free-solid-svg-icons/faRulerCombined"; +export { definition as faRulerHorizontal } from "@fortawesome/free-solid-svg-icons/faRulerHorizontal"; +export { definition as faRulerVertical } from "@fortawesome/free-solid-svg-icons/faRulerVertical"; +export { definition as faRunning } from "@fortawesome/free-solid-svg-icons/faRunning"; +export { definition as faRupee } from "@fortawesome/free-solid-svg-icons/faRupee"; +export { definition as faRupeeSign } from "@fortawesome/free-solid-svg-icons/faRupeeSign"; +export { definition as faRupiahSign } from "@fortawesome/free-solid-svg-icons/faRupiahSign"; +export { definition as faS } from "@fortawesome/free-solid-svg-icons/faS"; +export { definition as faSackDollar } from "@fortawesome/free-solid-svg-icons/faSackDollar"; +export { definition as faSackXmark } from "@fortawesome/free-solid-svg-icons/faSackXmark"; +export { definition as faSadCry } from "@fortawesome/free-solid-svg-icons/faSadCry"; +export { definition as faSadTear } from "@fortawesome/free-solid-svg-icons/faSadTear"; +export { definition as faSailboat } from "@fortawesome/free-solid-svg-icons/faSailboat"; +export { definition as faSatellite } from "@fortawesome/free-solid-svg-icons/faSatellite"; +export { definition as faSatelliteDish } from "@fortawesome/free-solid-svg-icons/faSatelliteDish"; +export { definition as faSave } from "@fortawesome/free-solid-svg-icons/faSave"; +export { definition as faScaleBalanced } from "@fortawesome/free-solid-svg-icons/faScaleBalanced"; +export { definition as faScaleUnbalanced } from "@fortawesome/free-solid-svg-icons/faScaleUnbalanced"; +export { definition as faScaleUnbalancedFlip } from "@fortawesome/free-solid-svg-icons/faScaleUnbalancedFlip"; +export { definition as faSchool } from "@fortawesome/free-solid-svg-icons/faSchool"; +export { definition as faSchoolCircleCheck } from "@fortawesome/free-solid-svg-icons/faSchoolCircleCheck"; +export { definition as faSchoolCircleExclamation } from "@fortawesome/free-solid-svg-icons/faSchoolCircleExclamation"; +export { definition as faSchoolCircleXmark } from "@fortawesome/free-solid-svg-icons/faSchoolCircleXmark"; +export { definition as faSchoolFlag } from "@fortawesome/free-solid-svg-icons/faSchoolFlag"; +export { definition as faSchoolLock } from "@fortawesome/free-solid-svg-icons/faSchoolLock"; +export { definition as faScissors } from "@fortawesome/free-solid-svg-icons/faScissors"; +export { definition as faScrewdriver } from "@fortawesome/free-solid-svg-icons/faScrewdriver"; +export { definition as faScrewdriverWrench } from "@fortawesome/free-solid-svg-icons/faScrewdriverWrench"; +export { definition as faScroll } from "@fortawesome/free-solid-svg-icons/faScroll"; +export { definition as faScrollTorah } from "@fortawesome/free-solid-svg-icons/faScrollTorah"; +export { definition as faSdCard } from "@fortawesome/free-solid-svg-icons/faSdCard"; +export { definition as faSearch } from "@fortawesome/free-solid-svg-icons/faSearch"; +export { definition as faSearchDollar } from "@fortawesome/free-solid-svg-icons/faSearchDollar"; +export { definition as faSearchLocation } from "@fortawesome/free-solid-svg-icons/faSearchLocation"; +export { definition as faSearchMinus } from "@fortawesome/free-solid-svg-icons/faSearchMinus"; +export { definition as faSearchPlus } from "@fortawesome/free-solid-svg-icons/faSearchPlus"; +export { definition as faSection } from "@fortawesome/free-solid-svg-icons/faSection"; +export { definition as faSeedling } from "@fortawesome/free-solid-svg-icons/faSeedling"; +export { definition as faServer } from "@fortawesome/free-solid-svg-icons/faServer"; +export { definition as faShapes } from "@fortawesome/free-solid-svg-icons/faShapes"; +export { definition as faShare } from "@fortawesome/free-solid-svg-icons/faShare"; +export { definition as faShareAlt } from "@fortawesome/free-solid-svg-icons/faShareAlt"; +export { definition as faShareAltSquare } from "@fortawesome/free-solid-svg-icons/faShareAltSquare"; +export { definition as faShareFromSquare } from "@fortawesome/free-solid-svg-icons/faShareFromSquare"; +export { definition as faShareNodes } from "@fortawesome/free-solid-svg-icons/faShareNodes"; +export { definition as faShareSquare } from "@fortawesome/free-solid-svg-icons/faShareSquare"; +export { definition as faSheetPlastic } from "@fortawesome/free-solid-svg-icons/faSheetPlastic"; +export { definition as faShekel } from "@fortawesome/free-solid-svg-icons/faShekel"; +export { definition as faShekelSign } from "@fortawesome/free-solid-svg-icons/faShekelSign"; +export { definition as faSheqel } from "@fortawesome/free-solid-svg-icons/faSheqel"; +export { definition as faSheqelSign } from "@fortawesome/free-solid-svg-icons/faSheqelSign"; +export { definition as faShield } from "@fortawesome/free-solid-svg-icons/faShield"; +export { definition as faShieldAlt } from "@fortawesome/free-solid-svg-icons/faShieldAlt"; +export { definition as faShieldBlank } from "@fortawesome/free-solid-svg-icons/faShieldBlank"; +export { definition as faShieldCat } from "@fortawesome/free-solid-svg-icons/faShieldCat"; +export { definition as faShieldDog } from "@fortawesome/free-solid-svg-icons/faShieldDog"; +export { definition as faShieldHalved } from "@fortawesome/free-solid-svg-icons/faShieldHalved"; +export { definition as faShieldHeart } from "@fortawesome/free-solid-svg-icons/faShieldHeart"; +export { definition as faShieldVirus } from "@fortawesome/free-solid-svg-icons/faShieldVirus"; +export { definition as faShip } from "@fortawesome/free-solid-svg-icons/faShip"; +export { definition as faShippingFast } from "@fortawesome/free-solid-svg-icons/faShippingFast"; +export { definition as faShirt } from "@fortawesome/free-solid-svg-icons/faShirt"; +export { definition as faShoePrints } from "@fortawesome/free-solid-svg-icons/faShoePrints"; +export { definition as faShop } from "@fortawesome/free-solid-svg-icons/faShop"; +export { definition as faShopLock } from "@fortawesome/free-solid-svg-icons/faShopLock"; +export { definition as faShopSlash } from "@fortawesome/free-solid-svg-icons/faShopSlash"; +export { definition as faShoppingBag } from "@fortawesome/free-solid-svg-icons/faShoppingBag"; +export { definition as faShoppingBasket } from "@fortawesome/free-solid-svg-icons/faShoppingBasket"; +export { definition as faShoppingCart } from "@fortawesome/free-solid-svg-icons/faShoppingCart"; +export { definition as faShower } from "@fortawesome/free-solid-svg-icons/faShower"; +export { definition as faShrimp } from "@fortawesome/free-solid-svg-icons/faShrimp"; +export { definition as faShuffle } from "@fortawesome/free-solid-svg-icons/faShuffle"; +export { definition as faShuttleSpace } from "@fortawesome/free-solid-svg-icons/faShuttleSpace"; +export { definition as faShuttleVan } from "@fortawesome/free-solid-svg-icons/faShuttleVan"; +export { definition as faSign } from "@fortawesome/free-solid-svg-icons/faSign"; +export { definition as faSignHanging } from "@fortawesome/free-solid-svg-icons/faSignHanging"; +export { definition as faSignIn } from "@fortawesome/free-solid-svg-icons/faSignIn"; +export { definition as faSignInAlt } from "@fortawesome/free-solid-svg-icons/faSignInAlt"; +export { definition as faSignLanguage } from "@fortawesome/free-solid-svg-icons/faSignLanguage"; +export { definition as faSignOut } from "@fortawesome/free-solid-svg-icons/faSignOut"; +export { definition as faSignOutAlt } from "@fortawesome/free-solid-svg-icons/faSignOutAlt"; +export { definition as faSignal } from "@fortawesome/free-solid-svg-icons/faSignal"; +export { definition as faSignal5 } from "@fortawesome/free-solid-svg-icons/faSignal5"; +export { definition as faSignalPerfect } from "@fortawesome/free-solid-svg-icons/faSignalPerfect"; +export { definition as faSignature } from "@fortawesome/free-solid-svg-icons/faSignature"; +export { definition as faSigning } from "@fortawesome/free-solid-svg-icons/faSigning"; +export { definition as faSignsPost } from "@fortawesome/free-solid-svg-icons/faSignsPost"; +export { definition as faSimCard } from "@fortawesome/free-solid-svg-icons/faSimCard"; +export { definition as faSink } from "@fortawesome/free-solid-svg-icons/faSink"; +export { definition as faSitemap } from "@fortawesome/free-solid-svg-icons/faSitemap"; +export { definition as faSkating } from "@fortawesome/free-solid-svg-icons/faSkating"; +export { definition as faSkiing } from "@fortawesome/free-solid-svg-icons/faSkiing"; +export { definition as faSkiingNordic } from "@fortawesome/free-solid-svg-icons/faSkiingNordic"; +export { definition as faSkull } from "@fortawesome/free-solid-svg-icons/faSkull"; +export { definition as faSkullCrossbones } from "@fortawesome/free-solid-svg-icons/faSkullCrossbones"; +export { definition as faSlash } from "@fortawesome/free-solid-svg-icons/faSlash"; +export { definition as faSleigh } from "@fortawesome/free-solid-svg-icons/faSleigh"; +export { definition as faSliders } from "@fortawesome/free-solid-svg-icons/faSliders"; +export { definition as faSlidersH } from "@fortawesome/free-solid-svg-icons/faSlidersH"; +export { definition as faSmile } from "@fortawesome/free-solid-svg-icons/faSmile"; +export { definition as faSmileBeam } from "@fortawesome/free-solid-svg-icons/faSmileBeam"; +export { definition as faSmileWink } from "@fortawesome/free-solid-svg-icons/faSmileWink"; +export { definition as faSmog } from "@fortawesome/free-solid-svg-icons/faSmog"; +export { definition as faSmoking } from "@fortawesome/free-solid-svg-icons/faSmoking"; +export { definition as faSmokingBan } from "@fortawesome/free-solid-svg-icons/faSmokingBan"; +export { definition as faSms } from "@fortawesome/free-solid-svg-icons/faSms"; +export { definition as faSnowboarding } from "@fortawesome/free-solid-svg-icons/faSnowboarding"; +export { definition as faSnowflake } from "@fortawesome/free-solid-svg-icons/faSnowflake"; +export { definition as faSnowman } from "@fortawesome/free-solid-svg-icons/faSnowman"; +export { definition as faSnowplow } from "@fortawesome/free-solid-svg-icons/faSnowplow"; +export { definition as faSoap } from "@fortawesome/free-solid-svg-icons/faSoap"; +export { definition as faSoccerBall } from "@fortawesome/free-solid-svg-icons/faSoccerBall"; +export { definition as faSocks } from "@fortawesome/free-solid-svg-icons/faSocks"; +export { definition as faSolarPanel } from "@fortawesome/free-solid-svg-icons/faSolarPanel"; +export { definition as faSort } from "@fortawesome/free-solid-svg-icons/faSort"; +export { definition as faSortAlphaAsc } from "@fortawesome/free-solid-svg-icons/faSortAlphaAsc"; +export { definition as faSortAlphaDesc } from "@fortawesome/free-solid-svg-icons/faSortAlphaDesc"; +export { definition as faSortAlphaDown } from "@fortawesome/free-solid-svg-icons/faSortAlphaDown"; +export { definition as faSortAlphaDownAlt } from "@fortawesome/free-solid-svg-icons/faSortAlphaDownAlt"; +export { definition as faSortAlphaUp } from "@fortawesome/free-solid-svg-icons/faSortAlphaUp"; +export { definition as faSortAlphaUpAlt } from "@fortawesome/free-solid-svg-icons/faSortAlphaUpAlt"; +export { definition as faSortAmountAsc } from "@fortawesome/free-solid-svg-icons/faSortAmountAsc"; +export { definition as faSortAmountDesc } from "@fortawesome/free-solid-svg-icons/faSortAmountDesc"; +export { definition as faSortAmountDown } from "@fortawesome/free-solid-svg-icons/faSortAmountDown"; +export { definition as faSortAmountDownAlt } from "@fortawesome/free-solid-svg-icons/faSortAmountDownAlt"; +export { definition as faSortAmountUp } from "@fortawesome/free-solid-svg-icons/faSortAmountUp"; +export { definition as faSortAmountUpAlt } from "@fortawesome/free-solid-svg-icons/faSortAmountUpAlt"; +export { definition as faSortAsc } from "@fortawesome/free-solid-svg-icons/faSortAsc"; +export { definition as faSortDesc } from "@fortawesome/free-solid-svg-icons/faSortDesc"; +export { definition as faSortDown } from "@fortawesome/free-solid-svg-icons/faSortDown"; +export { definition as faSortNumericAsc } from "@fortawesome/free-solid-svg-icons/faSortNumericAsc"; +export { definition as faSortNumericDesc } from "@fortawesome/free-solid-svg-icons/faSortNumericDesc"; +export { definition as faSortNumericDown } from "@fortawesome/free-solid-svg-icons/faSortNumericDown"; +export { definition as faSortNumericDownAlt } from "@fortawesome/free-solid-svg-icons/faSortNumericDownAlt"; +export { definition as faSortNumericUp } from "@fortawesome/free-solid-svg-icons/faSortNumericUp"; +export { definition as faSortNumericUpAlt } from "@fortawesome/free-solid-svg-icons/faSortNumericUpAlt"; +export { definition as faSortUp } from "@fortawesome/free-solid-svg-icons/faSortUp"; +export { definition as faSpa } from "@fortawesome/free-solid-svg-icons/faSpa"; +export { definition as faSpaceShuttle } from "@fortawesome/free-solid-svg-icons/faSpaceShuttle"; +export { definition as faSpaghettiMonsterFlying } from "@fortawesome/free-solid-svg-icons/faSpaghettiMonsterFlying"; +export { definition as faSpellCheck } from "@fortawesome/free-solid-svg-icons/faSpellCheck"; +export { definition as faSpider } from "@fortawesome/free-solid-svg-icons/faSpider"; +export { definition as faSpinner } from "@fortawesome/free-solid-svg-icons/faSpinner"; +export { definition as faSplotch } from "@fortawesome/free-solid-svg-icons/faSplotch"; +export { definition as faSpoon } from "@fortawesome/free-solid-svg-icons/faSpoon"; +export { definition as faSprayCan } from "@fortawesome/free-solid-svg-icons/faSprayCan"; +export { definition as faSprayCanSparkles } from "@fortawesome/free-solid-svg-icons/faSprayCanSparkles"; +export { definition as faSprout } from "@fortawesome/free-solid-svg-icons/faSprout"; +export { definition as faSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareArrowUpRight } from "@fortawesome/free-solid-svg-icons/faSquareArrowUpRight"; +export { definition as faSquareBinary } from "@fortawesome/free-solid-svg-icons/faSquareBinary"; +export { definition as faSquareCaretDown } from "@fortawesome/free-solid-svg-icons/faSquareCaretDown"; +export { definition as faSquareCaretLeft } from "@fortawesome/free-solid-svg-icons/faSquareCaretLeft"; +export { definition as faSquareCaretRight } from "@fortawesome/free-solid-svg-icons/faSquareCaretRight"; +export { definition as faSquareCaretUp } from "@fortawesome/free-solid-svg-icons/faSquareCaretUp"; +export { definition as faSquareCheck } from "@fortawesome/free-solid-svg-icons/faSquareCheck"; +export { definition as faSquareEnvelope } from "@fortawesome/free-solid-svg-icons/faSquareEnvelope"; +export { definition as faSquareFull } from "@fortawesome/free-solid-svg-icons/faSquareFull"; +export { definition as faSquareH } from "@fortawesome/free-solid-svg-icons/faSquareH"; +export { definition as faSquareMinus } from "@fortawesome/free-solid-svg-icons/faSquareMinus"; +export { definition as faSquareNfi } from "@fortawesome/free-solid-svg-icons/faSquareNfi"; +export { definition as faSquareParking } from "@fortawesome/free-solid-svg-icons/faSquareParking"; +export { definition as faSquarePen } from "@fortawesome/free-solid-svg-icons/faSquarePen"; +export { definition as faSquarePersonConfined } from "@fortawesome/free-solid-svg-icons/faSquarePersonConfined"; +export { definition as faSquarePhone } from "@fortawesome/free-solid-svg-icons/faSquarePhone"; +export { definition as faSquarePhoneFlip } from "@fortawesome/free-solid-svg-icons/faSquarePhoneFlip"; +export { definition as faSquarePlus } from "@fortawesome/free-solid-svg-icons/faSquarePlus"; +export { definition as faSquarePollHorizontal } from "@fortawesome/free-solid-svg-icons/faSquarePollHorizontal"; +export { definition as faSquarePollVertical } from "@fortawesome/free-solid-svg-icons/faSquarePollVertical"; +export { definition as faSquareRootAlt } from "@fortawesome/free-solid-svg-icons/faSquareRootAlt"; +export { definition as faSquareRootVariable } from "@fortawesome/free-solid-svg-icons/faSquareRootVariable"; +export { definition as faSquareRss } from "@fortawesome/free-solid-svg-icons/faSquareRss"; +export { definition as faSquareShareNodes } from "@fortawesome/free-solid-svg-icons/faSquareShareNodes"; +export { definition as faSquareUpRight } from "@fortawesome/free-solid-svg-icons/faSquareUpRight"; +export { definition as faSquareVirus } from "@fortawesome/free-solid-svg-icons/faSquareVirus"; +export { definition as faSquareXmark } from "@fortawesome/free-solid-svg-icons/faSquareXmark"; +export { definition as faStaffAesculapius } from "@fortawesome/free-solid-svg-icons/faStaffAesculapius"; +export { definition as faStaffSnake } from "@fortawesome/free-solid-svg-icons/faStaffSnake"; +export { definition as faStairs } from "@fortawesome/free-solid-svg-icons/faStairs"; +export { definition as faStamp } from "@fortawesome/free-solid-svg-icons/faStamp"; +export { definition as faStapler } from "@fortawesome/free-solid-svg-icons/faStapler"; +export { definition as faStar } from "@fortawesome/free-solid-svg-icons/faStar"; +export { definition as faStarAndCrescent } from "@fortawesome/free-solid-svg-icons/faStarAndCrescent"; +export { definition as faStarHalf } from "@fortawesome/free-solid-svg-icons/faStarHalf"; +export { definition as faStarHalfAlt } from "@fortawesome/free-solid-svg-icons/faStarHalfAlt"; +export { definition as faStarHalfStroke } from "@fortawesome/free-solid-svg-icons/faStarHalfStroke"; +export { definition as faStarOfDavid } from "@fortawesome/free-solid-svg-icons/faStarOfDavid"; +export { definition as faStarOfLife } from "@fortawesome/free-solid-svg-icons/faStarOfLife"; +export { definition as faStepBackward } from "@fortawesome/free-solid-svg-icons/faStepBackward"; +export { definition as faStepForward } from "@fortawesome/free-solid-svg-icons/faStepForward"; +export { definition as faSterlingSign } from "@fortawesome/free-solid-svg-icons/faSterlingSign"; +export { definition as faStethoscope } from "@fortawesome/free-solid-svg-icons/faStethoscope"; +export { definition as faStickyNote } from "@fortawesome/free-solid-svg-icons/faStickyNote"; +export { definition as faStop } from "@fortawesome/free-solid-svg-icons/faStop"; +export { definition as faStopCircle } from "@fortawesome/free-solid-svg-icons/faStopCircle"; +export { definition as faStopwatch } from "@fortawesome/free-solid-svg-icons/faStopwatch"; +export { definition as faStopwatch20 } from "@fortawesome/free-solid-svg-icons/faStopwatch20"; +export { definition as faStore } from "@fortawesome/free-solid-svg-icons/faStore"; +export { definition as faStoreAlt } from "@fortawesome/free-solid-svg-icons/faStoreAlt"; +export { definition as faStoreAltSlash } from "@fortawesome/free-solid-svg-icons/faStoreAltSlash"; +export { definition as faStoreSlash } from "@fortawesome/free-solid-svg-icons/faStoreSlash"; +export { definition as faStream } from "@fortawesome/free-solid-svg-icons/faStream"; +export { definition as faStreetView } from "@fortawesome/free-solid-svg-icons/faStreetView"; +export { definition as faStrikethrough } from "@fortawesome/free-solid-svg-icons/faStrikethrough"; +export { definition as faStroopwafel } from "@fortawesome/free-solid-svg-icons/faStroopwafel"; +export { definition as faSubscript } from "@fortawesome/free-solid-svg-icons/faSubscript"; +export { definition as faSubtract } from "@fortawesome/free-solid-svg-icons/faSubtract"; +export { definition as faSubway } from "@fortawesome/free-solid-svg-icons/faSubway"; +export { definition as faSuitcase } from "@fortawesome/free-solid-svg-icons/faSuitcase"; +export { definition as faSuitcaseMedical } from "@fortawesome/free-solid-svg-icons/faSuitcaseMedical"; +export { definition as faSuitcaseRolling } from "@fortawesome/free-solid-svg-icons/faSuitcaseRolling"; +export { definition as faSun } from "@fortawesome/free-solid-svg-icons/faSun"; +export { definition as faSunPlantWilt } from "@fortawesome/free-solid-svg-icons/faSunPlantWilt"; +export { definition as faSuperscript } from "@fortawesome/free-solid-svg-icons/faSuperscript"; +export { definition as faSurprise } from "@fortawesome/free-solid-svg-icons/faSurprise"; +export { definition as faSwatchbook } from "@fortawesome/free-solid-svg-icons/faSwatchbook"; +export { definition as faSwimmer } from "@fortawesome/free-solid-svg-icons/faSwimmer"; +export { definition as faSwimmingPool } from "@fortawesome/free-solid-svg-icons/faSwimmingPool"; +export { definition as faSynagogue } from "@fortawesome/free-solid-svg-icons/faSynagogue"; +export { definition as faSync } from "@fortawesome/free-solid-svg-icons/faSync"; +export { definition as faSyncAlt } from "@fortawesome/free-solid-svg-icons/faSyncAlt"; +export { definition as faSyringe } from "@fortawesome/free-solid-svg-icons/faSyringe"; +export { definition as faT } from "@fortawesome/free-solid-svg-icons/faT"; +export { definition as faTShirt } from "@fortawesome/free-solid-svg-icons/faTShirt"; +export { definition as faTable } from "@fortawesome/free-solid-svg-icons/faTable"; +export { definition as faTableCells } from "@fortawesome/free-solid-svg-icons/faTableCells"; +export { definition as faTableCellsColumnLock } from "@fortawesome/free-solid-svg-icons/faTableCellsColumnLock"; +export { definition as faTableCellsLarge } from "@fortawesome/free-solid-svg-icons/faTableCellsLarge"; +export { definition as faTableCellsRowLock } from "@fortawesome/free-solid-svg-icons/faTableCellsRowLock"; +export { definition as faTableCellsRowUnlock } from "@fortawesome/free-solid-svg-icons/faTableCellsRowUnlock"; +export { definition as faTableColumns } from "@fortawesome/free-solid-svg-icons/faTableColumns"; +export { definition as faTableList } from "@fortawesome/free-solid-svg-icons/faTableList"; +export { definition as faTableTennis } from "@fortawesome/free-solid-svg-icons/faTableTennis"; +export { definition as faTableTennisPaddleBall } from "@fortawesome/free-solid-svg-icons/faTableTennisPaddleBall"; +export { definition as faTablet } from "@fortawesome/free-solid-svg-icons/faTablet"; +export { definition as faTabletAlt } from "@fortawesome/free-solid-svg-icons/faTabletAlt"; +export { definition as faTabletAndroid } from "@fortawesome/free-solid-svg-icons/faTabletAndroid"; +export { definition as faTabletButton } from "@fortawesome/free-solid-svg-icons/faTabletButton"; +export { definition as faTabletScreenButton } from "@fortawesome/free-solid-svg-icons/faTabletScreenButton"; +export { definition as faTablets } from "@fortawesome/free-solid-svg-icons/faTablets"; +export { definition as faTachographDigital } from "@fortawesome/free-solid-svg-icons/faTachographDigital"; +export { definition as faTachometer } from "@fortawesome/free-solid-svg-icons/faTachometer"; +export { definition as faTachometerAlt } from "@fortawesome/free-solid-svg-icons/faTachometerAlt"; +export { definition as faTachometerAltAverage } from "@fortawesome/free-solid-svg-icons/faTachometerAltAverage"; +export { definition as faTachometerAltFast } from "@fortawesome/free-solid-svg-icons/faTachometerAltFast"; +export { definition as faTachometerAverage } from "@fortawesome/free-solid-svg-icons/faTachometerAverage"; +export { definition as faTachometerFast } from "@fortawesome/free-solid-svg-icons/faTachometerFast"; +export { definition as faTag } from "@fortawesome/free-solid-svg-icons/faTag"; +export { definition as faTags } from "@fortawesome/free-solid-svg-icons/faTags"; +export { definition as faTanakh } from "@fortawesome/free-solid-svg-icons/faTanakh"; +export { definition as faTape } from "@fortawesome/free-solid-svg-icons/faTape"; +export { definition as faTarp } from "@fortawesome/free-solid-svg-icons/faTarp"; +export { definition as faTarpDroplet } from "@fortawesome/free-solid-svg-icons/faTarpDroplet"; +export { definition as faTasks } from "@fortawesome/free-solid-svg-icons/faTasks"; +export { definition as faTasksAlt } from "@fortawesome/free-solid-svg-icons/faTasksAlt"; +export { definition as faTaxi } from "@fortawesome/free-solid-svg-icons/faTaxi"; +export { definition as faTeeth } from "@fortawesome/free-solid-svg-icons/faTeeth"; +export { definition as faTeethOpen } from "@fortawesome/free-solid-svg-icons/faTeethOpen"; +export { definition as faTeletype } from "@fortawesome/free-solid-svg-icons/faTeletype"; +export { definition as faTelevision } from "@fortawesome/free-solid-svg-icons/faTelevision"; +export { definition as faTemperature0 } from "@fortawesome/free-solid-svg-icons/faTemperature0"; +export { definition as faTemperature1 } from "@fortawesome/free-solid-svg-icons/faTemperature1"; +export { definition as faTemperature2 } from "@fortawesome/free-solid-svg-icons/faTemperature2"; +export { definition as faTemperature3 } from "@fortawesome/free-solid-svg-icons/faTemperature3"; +export { definition as faTemperature4 } from "@fortawesome/free-solid-svg-icons/faTemperature4"; +export { definition as faTemperatureArrowDown } from "@fortawesome/free-solid-svg-icons/faTemperatureArrowDown"; +export { definition as faTemperatureArrowUp } from "@fortawesome/free-solid-svg-icons/faTemperatureArrowUp"; +export { definition as faTemperatureDown } from "@fortawesome/free-solid-svg-icons/faTemperatureDown"; +export { definition as faTemperatureEmpty } from "@fortawesome/free-solid-svg-icons/faTemperatureEmpty"; +export { definition as faTemperatureFull } from "@fortawesome/free-solid-svg-icons/faTemperatureFull"; +export { definition as faTemperatureHalf } from "@fortawesome/free-solid-svg-icons/faTemperatureHalf"; +export { definition as faTemperatureHigh } from "@fortawesome/free-solid-svg-icons/faTemperatureHigh"; +export { definition as faTemperatureLow } from "@fortawesome/free-solid-svg-icons/faTemperatureLow"; +export { definition as faTemperatureQuarter } from "@fortawesome/free-solid-svg-icons/faTemperatureQuarter"; +export { definition as faTemperatureThreeQuarters } from "@fortawesome/free-solid-svg-icons/faTemperatureThreeQuarters"; +export { definition as faTemperatureUp } from "@fortawesome/free-solid-svg-icons/faTemperatureUp"; +export { definition as faTenge } from "@fortawesome/free-solid-svg-icons/faTenge"; +export { definition as faTengeSign } from "@fortawesome/free-solid-svg-icons/faTengeSign"; +export { definition as faTent } from "@fortawesome/free-solid-svg-icons/faTent"; +export { definition as faTentArrowDownToLine } from "@fortawesome/free-solid-svg-icons/faTentArrowDownToLine"; +export { definition as faTentArrowLeftRight } from "@fortawesome/free-solid-svg-icons/faTentArrowLeftRight"; +export { definition as faTentArrowTurnLeft } from "@fortawesome/free-solid-svg-icons/faTentArrowTurnLeft"; +export { definition as faTentArrowsDown } from "@fortawesome/free-solid-svg-icons/faTentArrowsDown"; +export { definition as faTents } from "@fortawesome/free-solid-svg-icons/faTents"; +export { definition as faTerminal } from "@fortawesome/free-solid-svg-icons/faTerminal"; +export { definition as faTextHeight } from "@fortawesome/free-solid-svg-icons/faTextHeight"; +export { definition as faTextSlash } from "@fortawesome/free-solid-svg-icons/faTextSlash"; +export { definition as faTextWidth } from "@fortawesome/free-solid-svg-icons/faTextWidth"; +export { definition as faTh } from "@fortawesome/free-solid-svg-icons/faTh"; +export { definition as faThLarge } from "@fortawesome/free-solid-svg-icons/faThLarge"; +export { definition as faThList } from "@fortawesome/free-solid-svg-icons/faThList"; +export { definition as faTheaterMasks } from "@fortawesome/free-solid-svg-icons/faTheaterMasks"; +export { definition as faThermometer } from "@fortawesome/free-solid-svg-icons/faThermometer"; +export { definition as faThermometer0 } from "@fortawesome/free-solid-svg-icons/faThermometer0"; +export { definition as faThermometer1 } from "@fortawesome/free-solid-svg-icons/faThermometer1"; +export { definition as faThermometer2 } from "@fortawesome/free-solid-svg-icons/faThermometer2"; +export { definition as faThermometer3 } from "@fortawesome/free-solid-svg-icons/faThermometer3"; +export { definition as faThermometer4 } from "@fortawesome/free-solid-svg-icons/faThermometer4"; +export { definition as faThermometerEmpty } from "@fortawesome/free-solid-svg-icons/faThermometerEmpty"; +export { definition as faThermometerFull } from "@fortawesome/free-solid-svg-icons/faThermometerFull"; +export { definition as faThermometerHalf } from "@fortawesome/free-solid-svg-icons/faThermometerHalf"; +export { definition as faThermometerQuarter } from "@fortawesome/free-solid-svg-icons/faThermometerQuarter"; +export { definition as faThermometerThreeQuarters } from "@fortawesome/free-solid-svg-icons/faThermometerThreeQuarters"; +export { definition as faThumbsDown } from "@fortawesome/free-solid-svg-icons/faThumbsDown"; +export { definition as faThumbsUp } from "@fortawesome/free-solid-svg-icons/faThumbsUp"; +export { definition as faThumbtack } from "@fortawesome/free-solid-svg-icons/faThumbtack"; +export { definition as faThumbtackSlash } from "@fortawesome/free-solid-svg-icons/faThumbtackSlash"; +export { definition as faThunderstorm } from "@fortawesome/free-solid-svg-icons/faThunderstorm"; +export { definition as faTicket } from "@fortawesome/free-solid-svg-icons/faTicket"; +export { definition as faTicketAlt } from "@fortawesome/free-solid-svg-icons/faTicketAlt"; +export { definition as faTicketSimple } from "@fortawesome/free-solid-svg-icons/faTicketSimple"; +export { definition as faTimeline } from "@fortawesome/free-solid-svg-icons/faTimeline"; +export { definition as faTimes } from "@fortawesome/free-solid-svg-icons/faTimes"; +export { definition as faTimesCircle } from "@fortawesome/free-solid-svg-icons/faTimesCircle"; +export { definition as faTimesRectangle } from "@fortawesome/free-solid-svg-icons/faTimesRectangle"; +export { definition as faTimesSquare } from "@fortawesome/free-solid-svg-icons/faTimesSquare"; +export { definition as faTint } from "@fortawesome/free-solid-svg-icons/faTint"; +export { definition as faTintSlash } from "@fortawesome/free-solid-svg-icons/faTintSlash"; +export { definition as faTired } from "@fortawesome/free-solid-svg-icons/faTired"; +export { definition as faToggleOff } from "@fortawesome/free-solid-svg-icons/faToggleOff"; +export { definition as faToggleOn } from "@fortawesome/free-solid-svg-icons/faToggleOn"; +export { definition as faToilet } from "@fortawesome/free-solid-svg-icons/faToilet"; +export { definition as faToiletPaper } from "@fortawesome/free-solid-svg-icons/faToiletPaper"; +export { definition as faToiletPaperSlash } from "@fortawesome/free-solid-svg-icons/faToiletPaperSlash"; +export { definition as faToiletPortable } from "@fortawesome/free-solid-svg-icons/faToiletPortable"; +export { definition as faToiletsPortable } from "@fortawesome/free-solid-svg-icons/faToiletsPortable"; +export { definition as faToolbox } from "@fortawesome/free-solid-svg-icons/faToolbox"; +export { definition as faTools } from "@fortawesome/free-solid-svg-icons/faTools"; +export { definition as faTooth } from "@fortawesome/free-solid-svg-icons/faTooth"; +export { definition as faTorah } from "@fortawesome/free-solid-svg-icons/faTorah"; +export { definition as faToriiGate } from "@fortawesome/free-solid-svg-icons/faToriiGate"; +export { definition as faTornado } from "@fortawesome/free-solid-svg-icons/faTornado"; +export { definition as faTowerBroadcast } from "@fortawesome/free-solid-svg-icons/faTowerBroadcast"; +export { definition as faTowerCell } from "@fortawesome/free-solid-svg-icons/faTowerCell"; +export { definition as faTowerObservation } from "@fortawesome/free-solid-svg-icons/faTowerObservation"; +export { definition as faTractor } from "@fortawesome/free-solid-svg-icons/faTractor"; +export { definition as faTrademark } from "@fortawesome/free-solid-svg-icons/faTrademark"; +export { definition as faTrafficLight } from "@fortawesome/free-solid-svg-icons/faTrafficLight"; +export { definition as faTrailer } from "@fortawesome/free-solid-svg-icons/faTrailer"; +export { definition as faTrain } from "@fortawesome/free-solid-svg-icons/faTrain"; +export { definition as faTrainSubway } from "@fortawesome/free-solid-svg-icons/faTrainSubway"; +export { definition as faTrainTram } from "@fortawesome/free-solid-svg-icons/faTrainTram"; +export { definition as faTram } from "@fortawesome/free-solid-svg-icons/faTram"; +export { definition as faTransgender } from "@fortawesome/free-solid-svg-icons/faTransgender"; +export { definition as faTransgenderAlt } from "@fortawesome/free-solid-svg-icons/faTransgenderAlt"; +export { definition as faTrash } from "@fortawesome/free-solid-svg-icons/faTrash"; +export { definition as faTrashAlt } from "@fortawesome/free-solid-svg-icons/faTrashAlt"; +export { definition as faTrashArrowUp } from "@fortawesome/free-solid-svg-icons/faTrashArrowUp"; +export { definition as faTrashCan } from "@fortawesome/free-solid-svg-icons/faTrashCan"; +export { definition as faTrashCanArrowUp } from "@fortawesome/free-solid-svg-icons/faTrashCanArrowUp"; +export { definition as faTrashRestore } from "@fortawesome/free-solid-svg-icons/faTrashRestore"; +export { definition as faTrashRestoreAlt } from "@fortawesome/free-solid-svg-icons/faTrashRestoreAlt"; +export { definition as faTree } from "@fortawesome/free-solid-svg-icons/faTree"; +export { definition as faTreeCity } from "@fortawesome/free-solid-svg-icons/faTreeCity"; +export { definition as faTriangleCircleSquare } from "@fortawesome/free-solid-svg-icons/faTriangleCircleSquare"; +export { definition as faTriangleExclamation } from "@fortawesome/free-solid-svg-icons/faTriangleExclamation"; +export { definition as faTrophy } from "@fortawesome/free-solid-svg-icons/faTrophy"; +export { definition as faTrowel } from "@fortawesome/free-solid-svg-icons/faTrowel"; +export { definition as faTrowelBricks } from "@fortawesome/free-solid-svg-icons/faTrowelBricks"; +export { definition as faTruck } from "@fortawesome/free-solid-svg-icons/faTruck"; +export { definition as faTruckArrowRight } from "@fortawesome/free-solid-svg-icons/faTruckArrowRight"; +export { definition as faTruckDroplet } from "@fortawesome/free-solid-svg-icons/faTruckDroplet"; +export { definition as faTruckFast } from "@fortawesome/free-solid-svg-icons/faTruckFast"; +export { definition as faTruckField } from "@fortawesome/free-solid-svg-icons/faTruckField"; +export { definition as faTruckFieldUn } from "@fortawesome/free-solid-svg-icons/faTruckFieldUn"; +export { definition as faTruckFront } from "@fortawesome/free-solid-svg-icons/faTruckFront"; +export { definition as faTruckLoading } from "@fortawesome/free-solid-svg-icons/faTruckLoading"; +export { definition as faTruckMedical } from "@fortawesome/free-solid-svg-icons/faTruckMedical"; +export { definition as faTruckMonster } from "@fortawesome/free-solid-svg-icons/faTruckMonster"; +export { definition as faTruckMoving } from "@fortawesome/free-solid-svg-icons/faTruckMoving"; +export { definition as faTruckPickup } from "@fortawesome/free-solid-svg-icons/faTruckPickup"; +export { definition as faTruckPlane } from "@fortawesome/free-solid-svg-icons/faTruckPlane"; +export { definition as faTruckRampBox } from "@fortawesome/free-solid-svg-icons/faTruckRampBox"; +export { definition as faTry } from "@fortawesome/free-solid-svg-icons/faTry"; +export { definition as faTty } from "@fortawesome/free-solid-svg-icons/faTty"; +export { definition as faTurkishLira } from "@fortawesome/free-solid-svg-icons/faTurkishLira"; +export { definition as faTurkishLiraSign } from "@fortawesome/free-solid-svg-icons/faTurkishLiraSign"; +export { definition as faTurnDown } from "@fortawesome/free-solid-svg-icons/faTurnDown"; +export { definition as faTurnUp } from "@fortawesome/free-solid-svg-icons/faTurnUp"; +export { definition as faTv } from "@fortawesome/free-solid-svg-icons/faTv"; +export { definition as faTvAlt } from "@fortawesome/free-solid-svg-icons/faTvAlt"; +export { definition as faU } from "@fortawesome/free-solid-svg-icons/faU"; +export { definition as faUmbrella } from "@fortawesome/free-solid-svg-icons/faUmbrella"; +export { definition as faUmbrellaBeach } from "@fortawesome/free-solid-svg-icons/faUmbrellaBeach"; +export { definition as faUnderline } from "@fortawesome/free-solid-svg-icons/faUnderline"; +export { definition as faUndo } from "@fortawesome/free-solid-svg-icons/faUndo"; +export { definition as faUndoAlt } from "@fortawesome/free-solid-svg-icons/faUndoAlt"; +export { definition as faUniversalAccess } from "@fortawesome/free-solid-svg-icons/faUniversalAccess"; +export { definition as faUniversity } from "@fortawesome/free-solid-svg-icons/faUniversity"; +export { definition as faUnlink } from "@fortawesome/free-solid-svg-icons/faUnlink"; +export { definition as faUnlock } from "@fortawesome/free-solid-svg-icons/faUnlock"; +export { definition as faUnlockAlt } from "@fortawesome/free-solid-svg-icons/faUnlockAlt"; +export { definition as faUnlockKeyhole } from "@fortawesome/free-solid-svg-icons/faUnlockKeyhole"; +export { definition as faUnsorted } from "@fortawesome/free-solid-svg-icons/faUnsorted"; +export { definition as faUpDown } from "@fortawesome/free-solid-svg-icons/faUpDown"; +export { definition as faUpDownLeftRight } from "@fortawesome/free-solid-svg-icons/faUpDownLeftRight"; +export { definition as faUpLong } from "@fortawesome/free-solid-svg-icons/faUpLong"; +export { definition as faUpRightAndDownLeftFromCenter } from "@fortawesome/free-solid-svg-icons/faUpRightAndDownLeftFromCenter"; +export { definition as faUpRightFromSquare } from "@fortawesome/free-solid-svg-icons/faUpRightFromSquare"; +export { definition as faUpload } from "@fortawesome/free-solid-svg-icons/faUpload"; +export { definition as faUsd } from "@fortawesome/free-solid-svg-icons/faUsd"; +export { definition as faUser } from "@fortawesome/free-solid-svg-icons/faUser"; +export { definition as faUserAlt } from "@fortawesome/free-solid-svg-icons/faUserAlt"; +export { definition as faUserAltSlash } from "@fortawesome/free-solid-svg-icons/faUserAltSlash"; +export { definition as faUserAstronaut } from "@fortawesome/free-solid-svg-icons/faUserAstronaut"; +export { definition as faUserCheck } from "@fortawesome/free-solid-svg-icons/faUserCheck"; +export { definition as faUserCircle } from "@fortawesome/free-solid-svg-icons/faUserCircle"; +export { definition as faUserClock } from "@fortawesome/free-solid-svg-icons/faUserClock"; +export { definition as faUserCog } from "@fortawesome/free-solid-svg-icons/faUserCog"; +export { definition as faUserDoctor } from "@fortawesome/free-solid-svg-icons/faUserDoctor"; +export { definition as faUserEdit } from "@fortawesome/free-solid-svg-icons/faUserEdit"; +export { definition as faUserFriends } from "@fortawesome/free-solid-svg-icons/faUserFriends"; +export { definition as faUserGear } from "@fortawesome/free-solid-svg-icons/faUserGear"; +export { definition as faUserGraduate } from "@fortawesome/free-solid-svg-icons/faUserGraduate"; +export { definition as faUserGroup } from "@fortawesome/free-solid-svg-icons/faUserGroup"; +export { definition as faUserInjured } from "@fortawesome/free-solid-svg-icons/faUserInjured"; +export { definition as faUserLarge } from "@fortawesome/free-solid-svg-icons/faUserLarge"; +export { definition as faUserLargeSlash } from "@fortawesome/free-solid-svg-icons/faUserLargeSlash"; +export { definition as faUserLock } from "@fortawesome/free-solid-svg-icons/faUserLock"; +export { definition as faUserMd } from "@fortawesome/free-solid-svg-icons/faUserMd"; +export { definition as faUserMinus } from "@fortawesome/free-solid-svg-icons/faUserMinus"; +export { definition as faUserNinja } from "@fortawesome/free-solid-svg-icons/faUserNinja"; +export { definition as faUserNurse } from "@fortawesome/free-solid-svg-icons/faUserNurse"; +export { definition as faUserPen } from "@fortawesome/free-solid-svg-icons/faUserPen"; +export { definition as faUserPlus } from "@fortawesome/free-solid-svg-icons/faUserPlus"; +export { definition as faUserSecret } from "@fortawesome/free-solid-svg-icons/faUserSecret"; +export { definition as faUserShield } from "@fortawesome/free-solid-svg-icons/faUserShield"; +export { definition as faUserSlash } from "@fortawesome/free-solid-svg-icons/faUserSlash"; +export { definition as faUserTag } from "@fortawesome/free-solid-svg-icons/faUserTag"; +export { definition as faUserTie } from "@fortawesome/free-solid-svg-icons/faUserTie"; +export { definition as faUserTimes } from "@fortawesome/free-solid-svg-icons/faUserTimes"; +export { definition as faUserXmark } from "@fortawesome/free-solid-svg-icons/faUserXmark"; +export { definition as faUsers } from "@fortawesome/free-solid-svg-icons/faUsers"; +export { definition as faUsersBetweenLines } from "@fortawesome/free-solid-svg-icons/faUsersBetweenLines"; +export { definition as faUsersCog } from "@fortawesome/free-solid-svg-icons/faUsersCog"; +export { definition as faUsersGear } from "@fortawesome/free-solid-svg-icons/faUsersGear"; +export { definition as faUsersLine } from "@fortawesome/free-solid-svg-icons/faUsersLine"; +export { definition as faUsersRays } from "@fortawesome/free-solid-svg-icons/faUsersRays"; +export { definition as faUsersRectangle } from "@fortawesome/free-solid-svg-icons/faUsersRectangle"; +export { definition as faUsersSlash } from "@fortawesome/free-solid-svg-icons/faUsersSlash"; +export { definition as faUsersViewfinder } from "@fortawesome/free-solid-svg-icons/faUsersViewfinder"; +export { definition as faUtensilSpoon } from "@fortawesome/free-solid-svg-icons/faUtensilSpoon"; +export { definition as faUtensils } from "@fortawesome/free-solid-svg-icons/faUtensils"; +export { definition as faV } from "@fortawesome/free-solid-svg-icons/faV"; +export { definition as faVanShuttle } from "@fortawesome/free-solid-svg-icons/faVanShuttle"; +export { definition as faVault } from "@fortawesome/free-solid-svg-icons/faVault"; +export { definition as faVcard } from "@fortawesome/free-solid-svg-icons/faVcard"; +export { definition as faVectorSquare } from "@fortawesome/free-solid-svg-icons/faVectorSquare"; +export { definition as faVenus } from "@fortawesome/free-solid-svg-icons/faVenus"; +export { definition as faVenusDouble } from "@fortawesome/free-solid-svg-icons/faVenusDouble"; +export { definition as faVenusMars } from "@fortawesome/free-solid-svg-icons/faVenusMars"; +export { definition as faVest } from "@fortawesome/free-solid-svg-icons/faVest"; +export { definition as faVestPatches } from "@fortawesome/free-solid-svg-icons/faVestPatches"; +export { definition as faVial } from "@fortawesome/free-solid-svg-icons/faVial"; +export { definition as faVialCircleCheck } from "@fortawesome/free-solid-svg-icons/faVialCircleCheck"; +export { definition as faVialVirus } from "@fortawesome/free-solid-svg-icons/faVialVirus"; +export { definition as faVials } from "@fortawesome/free-solid-svg-icons/faVials"; +export { definition as faVideo } from "@fortawesome/free-solid-svg-icons/faVideo"; +export { definition as faVideoCamera } from "@fortawesome/free-solid-svg-icons/faVideoCamera"; +export { definition as faVideoSlash } from "@fortawesome/free-solid-svg-icons/faVideoSlash"; +export { definition as faVihara } from "@fortawesome/free-solid-svg-icons/faVihara"; +export { definition as faVirus } from "@fortawesome/free-solid-svg-icons/faVirus"; +export { definition as faVirusCovid } from "@fortawesome/free-solid-svg-icons/faVirusCovid"; +export { definition as faVirusCovidSlash } from "@fortawesome/free-solid-svg-icons/faVirusCovidSlash"; +export { definition as faVirusSlash } from "@fortawesome/free-solid-svg-icons/faVirusSlash"; +export { definition as faViruses } from "@fortawesome/free-solid-svg-icons/faViruses"; +export { definition as faVoicemail } from "@fortawesome/free-solid-svg-icons/faVoicemail"; +export { definition as faVolcano } from "@fortawesome/free-solid-svg-icons/faVolcano"; +export { definition as faVolleyball } from "@fortawesome/free-solid-svg-icons/faVolleyball"; +export { definition as faVolleyballBall } from "@fortawesome/free-solid-svg-icons/faVolleyballBall"; +export { definition as faVolumeControlPhone } from "@fortawesome/free-solid-svg-icons/faVolumeControlPhone"; +export { definition as faVolumeDown } from "@fortawesome/free-solid-svg-icons/faVolumeDown"; +export { definition as faVolumeHigh } from "@fortawesome/free-solid-svg-icons/faVolumeHigh"; +export { definition as faVolumeLow } from "@fortawesome/free-solid-svg-icons/faVolumeLow"; +export { definition as faVolumeMute } from "@fortawesome/free-solid-svg-icons/faVolumeMute"; +export { definition as faVolumeOff } from "@fortawesome/free-solid-svg-icons/faVolumeOff"; +export { definition as faVolumeTimes } from "@fortawesome/free-solid-svg-icons/faVolumeTimes"; +export { definition as faVolumeUp } from "@fortawesome/free-solid-svg-icons/faVolumeUp"; +export { definition as faVolumeXmark } from "@fortawesome/free-solid-svg-icons/faVolumeXmark"; +export { definition as faVoteYea } from "@fortawesome/free-solid-svg-icons/faVoteYea"; +export { definition as faVrCardboard } from "@fortawesome/free-solid-svg-icons/faVrCardboard"; +export { definition as faW } from "@fortawesome/free-solid-svg-icons/faW"; +export { definition as faWalkieTalkie } from "@fortawesome/free-solid-svg-icons/faWalkieTalkie"; +export { definition as faWalking } from "@fortawesome/free-solid-svg-icons/faWalking"; +export { definition as faWallet } from "@fortawesome/free-solid-svg-icons/faWallet"; +export { definition as faWandMagic } from "@fortawesome/free-solid-svg-icons/faWandMagic"; +export { definition as faWandMagicSparkles } from "@fortawesome/free-solid-svg-icons/faWandMagicSparkles"; +export { definition as faWandSparkles } from "@fortawesome/free-solid-svg-icons/faWandSparkles"; +export { definition as faWarehouse } from "@fortawesome/free-solid-svg-icons/faWarehouse"; +export { definition as faWarning } from "@fortawesome/free-solid-svg-icons/faWarning"; +export { definition as faWater } from "@fortawesome/free-solid-svg-icons/faWater"; +export { definition as faWaterLadder } from "@fortawesome/free-solid-svg-icons/faWaterLadder"; +export { definition as faWaveSquare } from "@fortawesome/free-solid-svg-icons/faWaveSquare"; +export { definition as faWebAwesome } from "@fortawesome/free-solid-svg-icons/faWebAwesome"; +export { definition as faWeight } from "@fortawesome/free-solid-svg-icons/faWeight"; +export { definition as faWeightHanging } from "@fortawesome/free-solid-svg-icons/faWeightHanging"; +export { definition as faWeightScale } from "@fortawesome/free-solid-svg-icons/faWeightScale"; +export { definition as faWheatAlt } from "@fortawesome/free-solid-svg-icons/faWheatAlt"; +export { definition as faWheatAwn } from "@fortawesome/free-solid-svg-icons/faWheatAwn"; +export { definition as faWheatAwnCircleExclamation } from "@fortawesome/free-solid-svg-icons/faWheatAwnCircleExclamation"; +export { definition as faWheelchair } from "@fortawesome/free-solid-svg-icons/faWheelchair"; +export { definition as faWheelchairAlt } from "@fortawesome/free-solid-svg-icons/faWheelchairAlt"; +export { definition as faWheelchairMove } from "@fortawesome/free-solid-svg-icons/faWheelchairMove"; +export { definition as faWhiskeyGlass } from "@fortawesome/free-solid-svg-icons/faWhiskeyGlass"; +export { definition as faWifi } from "@fortawesome/free-solid-svg-icons/faWifi"; +export { definition as faWifi3 } from "@fortawesome/free-solid-svg-icons/faWifi3"; +export { definition as faWifiStrong } from "@fortawesome/free-solid-svg-icons/faWifiStrong"; +export { definition as faWind } from "@fortawesome/free-solid-svg-icons/faWind"; +export { definition as faWindowClose } from "@fortawesome/free-solid-svg-icons/faWindowClose"; +export { definition as faWindowMaximize } from "@fortawesome/free-solid-svg-icons/faWindowMaximize"; +export { definition as faWindowMinimize } from "@fortawesome/free-solid-svg-icons/faWindowMinimize"; +export { definition as faWindowRestore } from "@fortawesome/free-solid-svg-icons/faWindowRestore"; +export { definition as faWineBottle } from "@fortawesome/free-solid-svg-icons/faWineBottle"; +export { definition as faWineGlass } from "@fortawesome/free-solid-svg-icons/faWineGlass"; +export { definition as faWineGlassAlt } from "@fortawesome/free-solid-svg-icons/faWineGlassAlt"; +export { definition as faWineGlassEmpty } from "@fortawesome/free-solid-svg-icons/faWineGlassEmpty"; +export { definition as faWon } from "@fortawesome/free-solid-svg-icons/faWon"; +export { definition as faWonSign } from "@fortawesome/free-solid-svg-icons/faWonSign"; +export { definition as faWorm } from "@fortawesome/free-solid-svg-icons/faWorm"; +export { definition as faWrench } from "@fortawesome/free-solid-svg-icons/faWrench"; +export { definition as faX } from "@fortawesome/free-solid-svg-icons/faX"; +export { definition as faXRay } from "@fortawesome/free-solid-svg-icons/faXRay"; +export { definition as faXmark } from "@fortawesome/free-solid-svg-icons/faXmark"; +export { definition as faXmarkCircle } from "@fortawesome/free-solid-svg-icons/faXmarkCircle"; +export { definition as faXmarkSquare } from "@fortawesome/free-solid-svg-icons/faXmarkSquare"; +export { definition as faXmarksLines } from "@fortawesome/free-solid-svg-icons/faXmarksLines"; +export { definition as faY } from "@fortawesome/free-solid-svg-icons/faY"; +export { definition as faYen } from "@fortawesome/free-solid-svg-icons/faYen"; +export { definition as faYenSign } from "@fortawesome/free-solid-svg-icons/faYenSign"; +export { definition as faYinYang } from "@fortawesome/free-solid-svg-icons/faYinYang"; +export { definition as faZ } from "@fortawesome/free-solid-svg-icons/faZ"; +export { definition as faZap } from "@fortawesome/free-solid-svg-icons/faZap"; +export { definition as fa42Group } from "@fortawesome/free-brands-svg-icons/fa42Group"; +export { definition as fa500px } from "@fortawesome/free-brands-svg-icons/fa500px"; +export { definition as faAccessibleIcon } from "@fortawesome/free-brands-svg-icons/faAccessibleIcon"; +export { definition as faAccusoft } from "@fortawesome/free-brands-svg-icons/faAccusoft"; +export { definition as faAdn } from "@fortawesome/free-brands-svg-icons/faAdn"; +export { definition as faAdversal } from "@fortawesome/free-brands-svg-icons/faAdversal"; +export { definition as faAffiliatetheme } from "@fortawesome/free-brands-svg-icons/faAffiliatetheme"; +export { definition as faAirbnb } from "@fortawesome/free-brands-svg-icons/faAirbnb"; +export { definition as faAlgolia } from "@fortawesome/free-brands-svg-icons/faAlgolia"; +export { definition as faAlipay } from "@fortawesome/free-brands-svg-icons/faAlipay"; +export { definition as faAmazon } from "@fortawesome/free-brands-svg-icons/faAmazon"; +export { definition as faAmazonPay } from "@fortawesome/free-brands-svg-icons/faAmazonPay"; +export { definition as faAmilia } from "@fortawesome/free-brands-svg-icons/faAmilia"; +export { definition as faAndroid } from "@fortawesome/free-brands-svg-icons/faAndroid"; +export { definition as faAngellist } from "@fortawesome/free-brands-svg-icons/faAngellist"; +export { definition as faAngrycreative } from "@fortawesome/free-brands-svg-icons/faAngrycreative"; +export { definition as faAngular } from "@fortawesome/free-brands-svg-icons/faAngular"; +export { definition as faAppStore } from "@fortawesome/free-brands-svg-icons/faAppStore"; +export { definition as faAppStoreIos } from "@fortawesome/free-brands-svg-icons/faAppStoreIos"; +export { definition as faApper } from "@fortawesome/free-brands-svg-icons/faApper"; +export { definition as faApple } from "@fortawesome/free-brands-svg-icons/faApple"; +export { definition as faApplePay } from "@fortawesome/free-brands-svg-icons/faApplePay"; +export { definition as faArtstation } from "@fortawesome/free-brands-svg-icons/faArtstation"; +export { definition as faAsymmetrik } from "@fortawesome/free-brands-svg-icons/faAsymmetrik"; +export { definition as faAtlassian } from "@fortawesome/free-brands-svg-icons/faAtlassian"; +export { definition as faAudible } from "@fortawesome/free-brands-svg-icons/faAudible"; +export { definition as faAutoprefixer } from "@fortawesome/free-brands-svg-icons/faAutoprefixer"; +export { definition as faAvianex } from "@fortawesome/free-brands-svg-icons/faAvianex"; +export { definition as faAviato } from "@fortawesome/free-brands-svg-icons/faAviato"; +export { definition as faAws } from "@fortawesome/free-brands-svg-icons/faAws"; +export { definition as faBandcamp } from "@fortawesome/free-brands-svg-icons/faBandcamp"; +export { definition as faBattleNet } from "@fortawesome/free-brands-svg-icons/faBattleNet"; +export { definition as faBehance } from "@fortawesome/free-brands-svg-icons/faBehance"; +export { definition as faBehanceSquare } from "@fortawesome/free-brands-svg-icons/faBehanceSquare"; +export { definition as faBilibili } from "@fortawesome/free-brands-svg-icons/faBilibili"; +export { definition as faBimobject } from "@fortawesome/free-brands-svg-icons/faBimobject"; +export { definition as faBitbucket } from "@fortawesome/free-brands-svg-icons/faBitbucket"; +export { definition as faBitcoin } from "@fortawesome/free-brands-svg-icons/faBitcoin"; +export { definition as faBity } from "@fortawesome/free-brands-svg-icons/faBity"; +export { definition as faBlackTie } from "@fortawesome/free-brands-svg-icons/faBlackTie"; +export { definition as faBlackberry } from "@fortawesome/free-brands-svg-icons/faBlackberry"; +export { definition as faBlogger } from "@fortawesome/free-brands-svg-icons/faBlogger"; +export { definition as faBloggerB } from "@fortawesome/free-brands-svg-icons/faBloggerB"; +export { definition as faBluesky } from "@fortawesome/free-brands-svg-icons/faBluesky"; +export { definition as faBluetooth } from "@fortawesome/free-brands-svg-icons/faBluetooth"; +export { definition as faBluetoothB } from "@fortawesome/free-brands-svg-icons/faBluetoothB"; +export { definition as faBootstrap } from "@fortawesome/free-brands-svg-icons/faBootstrap"; +export { definition as faBots } from "@fortawesome/free-brands-svg-icons/faBots"; +export { definition as faBrave } from "@fortawesome/free-brands-svg-icons/faBrave"; +export { definition as faBraveReverse } from "@fortawesome/free-brands-svg-icons/faBraveReverse"; +export { definition as faBtc } from "@fortawesome/free-brands-svg-icons/faBtc"; +export { definition as faBuffer } from "@fortawesome/free-brands-svg-icons/faBuffer"; +export { definition as faBuromobelexperte } from "@fortawesome/free-brands-svg-icons/faBuromobelexperte"; +export { definition as faBuyNLarge } from "@fortawesome/free-brands-svg-icons/faBuyNLarge"; +export { definition as faBuysellads } from "@fortawesome/free-brands-svg-icons/faBuysellads"; +export { definition as faCanadianMapleLeaf } from "@fortawesome/free-brands-svg-icons/faCanadianMapleLeaf"; +export { definition as faCcAmazonPay } from "@fortawesome/free-brands-svg-icons/faCcAmazonPay"; +export { definition as faCcAmex } from "@fortawesome/free-brands-svg-icons/faCcAmex"; +export { definition as faCcApplePay } from "@fortawesome/free-brands-svg-icons/faCcApplePay"; +export { definition as faCcDinersClub } from "@fortawesome/free-brands-svg-icons/faCcDinersClub"; +export { definition as faCcDiscover } from "@fortawesome/free-brands-svg-icons/faCcDiscover"; +export { definition as faCcJcb } from "@fortawesome/free-brands-svg-icons/faCcJcb"; +export { definition as faCcMastercard } from "@fortawesome/free-brands-svg-icons/faCcMastercard"; +export { definition as faCcPaypal } from "@fortawesome/free-brands-svg-icons/faCcPaypal"; +export { definition as faCcStripe } from "@fortawesome/free-brands-svg-icons/faCcStripe"; +export { definition as faCcVisa } from "@fortawesome/free-brands-svg-icons/faCcVisa"; +export { definition as faCentercode } from "@fortawesome/free-brands-svg-icons/faCentercode"; +export { definition as faCentos } from "@fortawesome/free-brands-svg-icons/faCentos"; +export { definition as faChrome } from "@fortawesome/free-brands-svg-icons/faChrome"; +export { definition as faChromecast } from "@fortawesome/free-brands-svg-icons/faChromecast"; +export { definition as faCloudflare } from "@fortawesome/free-brands-svg-icons/faCloudflare"; +export { definition as faCloudscale } from "@fortawesome/free-brands-svg-icons/faCloudscale"; +export { definition as faCloudsmith } from "@fortawesome/free-brands-svg-icons/faCloudsmith"; +export { definition as faCloudversify } from "@fortawesome/free-brands-svg-icons/faCloudversify"; +export { definition as faCmplid } from "@fortawesome/free-brands-svg-icons/faCmplid"; +export { definition as faCodepen } from "@fortawesome/free-brands-svg-icons/faCodepen"; +export { definition as faCodiepie } from "@fortawesome/free-brands-svg-icons/faCodiepie"; +export { definition as faConfluence } from "@fortawesome/free-brands-svg-icons/faConfluence"; +export { definition as faConnectdevelop } from "@fortawesome/free-brands-svg-icons/faConnectdevelop"; +export { definition as faContao } from "@fortawesome/free-brands-svg-icons/faContao"; +export { definition as faCottonBureau } from "@fortawesome/free-brands-svg-icons/faCottonBureau"; +export { definition as faCpanel } from "@fortawesome/free-brands-svg-icons/faCpanel"; +export { definition as faCreativeCommons } from "@fortawesome/free-brands-svg-icons/faCreativeCommons"; +export { definition as faCreativeCommonsBy } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsBy"; +export { definition as faCreativeCommonsNc } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsNc"; +export { definition as faCreativeCommonsNcEu } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsNcEu"; +export { definition as faCreativeCommonsNcJp } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsNcJp"; +export { definition as faCreativeCommonsNd } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsNd"; +export { definition as faCreativeCommonsPd } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsPd"; +export { definition as faCreativeCommonsPdAlt } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsPdAlt"; +export { definition as faCreativeCommonsRemix } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsRemix"; +export { definition as faCreativeCommonsSa } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsSa"; +export { definition as faCreativeCommonsSampling } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsSampling"; +export { definition as faCreativeCommonsSamplingPlus } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsSamplingPlus"; +export { definition as faCreativeCommonsShare } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsShare"; +export { definition as faCreativeCommonsZero } from "@fortawesome/free-brands-svg-icons/faCreativeCommonsZero"; +export { definition as faCriticalRole } from "@fortawesome/free-brands-svg-icons/faCriticalRole"; +export { definition as faCss } from "@fortawesome/free-brands-svg-icons/faCss"; +export { definition as faCss3 } from "@fortawesome/free-brands-svg-icons/faCss3"; +export { definition as faCss3Alt } from "@fortawesome/free-brands-svg-icons/faCss3Alt"; +export { definition as faCuttlefish } from "@fortawesome/free-brands-svg-icons/faCuttlefish"; +export { definition as faDAndD } from "@fortawesome/free-brands-svg-icons/faDAndD"; +export { definition as faDAndDBeyond } from "@fortawesome/free-brands-svg-icons/faDAndDBeyond"; +export { definition as faDailymotion } from "@fortawesome/free-brands-svg-icons/faDailymotion"; +export { definition as faDartLang } from "@fortawesome/free-brands-svg-icons/faDartLang"; +export { definition as faDashcube } from "@fortawesome/free-brands-svg-icons/faDashcube"; +export { definition as faDebian } from "@fortawesome/free-brands-svg-icons/faDebian"; +export { definition as faDeezer } from "@fortawesome/free-brands-svg-icons/faDeezer"; +export { definition as faDelicious } from "@fortawesome/free-brands-svg-icons/faDelicious"; +export { definition as faDeploydog } from "@fortawesome/free-brands-svg-icons/faDeploydog"; +export { definition as faDeskpro } from "@fortawesome/free-brands-svg-icons/faDeskpro"; +export { definition as faDev } from "@fortawesome/free-brands-svg-icons/faDev"; +export { definition as faDeviantart } from "@fortawesome/free-brands-svg-icons/faDeviantart"; +export { definition as faDhl } from "@fortawesome/free-brands-svg-icons/faDhl"; +export { definition as faDiaspora } from "@fortawesome/free-brands-svg-icons/faDiaspora"; +export { definition as faDigg } from "@fortawesome/free-brands-svg-icons/faDigg"; +export { definition as faDigitalOcean } from "@fortawesome/free-brands-svg-icons/faDigitalOcean"; +export { definition as faDiscord } from "@fortawesome/free-brands-svg-icons/faDiscord"; +export { definition as faDiscourse } from "@fortawesome/free-brands-svg-icons/faDiscourse"; +export { definition as faDochub } from "@fortawesome/free-brands-svg-icons/faDochub"; +export { definition as faDocker } from "@fortawesome/free-brands-svg-icons/faDocker"; +export { definition as faDraft2digital } from "@fortawesome/free-brands-svg-icons/faDraft2digital"; +export { definition as faDribbble } from "@fortawesome/free-brands-svg-icons/faDribbble"; +export { definition as faDribbbleSquare } from "@fortawesome/free-brands-svg-icons/faDribbbleSquare"; +export { definition as faDropbox } from "@fortawesome/free-brands-svg-icons/faDropbox"; +export { definition as faDrupal } from "@fortawesome/free-brands-svg-icons/faDrupal"; +export { definition as faDyalog } from "@fortawesome/free-brands-svg-icons/faDyalog"; +export { definition as faEarlybirds } from "@fortawesome/free-brands-svg-icons/faEarlybirds"; +export { definition as faEbay } from "@fortawesome/free-brands-svg-icons/faEbay"; +export { definition as faEdge } from "@fortawesome/free-brands-svg-icons/faEdge"; +export { definition as faEdgeLegacy } from "@fortawesome/free-brands-svg-icons/faEdgeLegacy"; +export { definition as faElementor } from "@fortawesome/free-brands-svg-icons/faElementor"; +export { definition as faEllo } from "@fortawesome/free-brands-svg-icons/faEllo"; +export { definition as faEmber } from "@fortawesome/free-brands-svg-icons/faEmber"; +export { definition as faEmpire } from "@fortawesome/free-brands-svg-icons/faEmpire"; +export { definition as faEnvira } from "@fortawesome/free-brands-svg-icons/faEnvira"; +export { definition as faErlang } from "@fortawesome/free-brands-svg-icons/faErlang"; +export { definition as faEthereum } from "@fortawesome/free-brands-svg-icons/faEthereum"; +export { definition as faEtsy } from "@fortawesome/free-brands-svg-icons/faEtsy"; +export { definition as faEvernote } from "@fortawesome/free-brands-svg-icons/faEvernote"; +export { definition as faExpeditedssl } from "@fortawesome/free-brands-svg-icons/faExpeditedssl"; +export { definition as faFacebook } from "@fortawesome/free-brands-svg-icons/faFacebook"; +export { definition as faFacebookF } from "@fortawesome/free-brands-svg-icons/faFacebookF"; +export { definition as faFacebookMessenger } from "@fortawesome/free-brands-svg-icons/faFacebookMessenger"; +export { definition as faFacebookSquare } from "@fortawesome/free-brands-svg-icons/faFacebookSquare"; +export { definition as faFantasyFlightGames } from "@fortawesome/free-brands-svg-icons/faFantasyFlightGames"; +export { definition as faFedex } from "@fortawesome/free-brands-svg-icons/faFedex"; +export { definition as faFedora } from "@fortawesome/free-brands-svg-icons/faFedora"; +export { definition as faFigma } from "@fortawesome/free-brands-svg-icons/faFigma"; +export { definition as faFilesPinwheel } from "@fortawesome/free-brands-svg-icons/faFilesPinwheel"; +export { definition as faFirefox } from "@fortawesome/free-brands-svg-icons/faFirefox"; +export { definition as faFirefoxBrowser } from "@fortawesome/free-brands-svg-icons/faFirefoxBrowser"; +export { definition as faFirstOrder } from "@fortawesome/free-brands-svg-icons/faFirstOrder"; +export { definition as faFirstOrderAlt } from "@fortawesome/free-brands-svg-icons/faFirstOrderAlt"; +export { definition as faFirstdraft } from "@fortawesome/free-brands-svg-icons/faFirstdraft"; +export { definition as faFlickr } from "@fortawesome/free-brands-svg-icons/faFlickr"; +export { definition as faFlipboard } from "@fortawesome/free-brands-svg-icons/faFlipboard"; +export { definition as faFlutter } from "@fortawesome/free-brands-svg-icons/faFlutter"; +export { definition as faFly } from "@fortawesome/free-brands-svg-icons/faFly"; +export { definition as faFontAwesomeAlt } from "@fortawesome/free-brands-svg-icons/faFontAwesomeAlt"; +export { definition as faFonticons } from "@fortawesome/free-brands-svg-icons/faFonticons"; +export { definition as faFonticonsFi } from "@fortawesome/free-brands-svg-icons/faFonticonsFi"; +export { definition as faFortAwesome } from "@fortawesome/free-brands-svg-icons/faFortAwesome"; +export { definition as faFortAwesomeAlt } from "@fortawesome/free-brands-svg-icons/faFortAwesomeAlt"; +export { definition as faForumbee } from "@fortawesome/free-brands-svg-icons/faForumbee"; +export { definition as faFoursquare } from "@fortawesome/free-brands-svg-icons/faFoursquare"; +export { definition as faFreeCodeCamp } from "@fortawesome/free-brands-svg-icons/faFreeCodeCamp"; +export { definition as faFreebsd } from "@fortawesome/free-brands-svg-icons/faFreebsd"; +export { definition as faFulcrum } from "@fortawesome/free-brands-svg-icons/faFulcrum"; +export { definition as faGalacticRepublic } from "@fortawesome/free-brands-svg-icons/faGalacticRepublic"; +export { definition as faGalacticSenate } from "@fortawesome/free-brands-svg-icons/faGalacticSenate"; +export { definition as faGetPocket } from "@fortawesome/free-brands-svg-icons/faGetPocket"; +export { definition as faGg } from "@fortawesome/free-brands-svg-icons/faGg"; +export { definition as faGgCircle } from "@fortawesome/free-brands-svg-icons/faGgCircle"; +export { definition as faGit } from "@fortawesome/free-brands-svg-icons/faGit"; +export { definition as faGitAlt } from "@fortawesome/free-brands-svg-icons/faGitAlt"; +export { definition as faGitSquare } from "@fortawesome/free-brands-svg-icons/faGitSquare"; +export { definition as faGithub } from "@fortawesome/free-brands-svg-icons/faGithub"; +export { definition as faGithubAlt } from "@fortawesome/free-brands-svg-icons/faGithubAlt"; +export { definition as faGithubSquare } from "@fortawesome/free-brands-svg-icons/faGithubSquare"; +export { definition as faGitkraken } from "@fortawesome/free-brands-svg-icons/faGitkraken"; +export { definition as faGitlab } from "@fortawesome/free-brands-svg-icons/faGitlab"; +export { definition as faGitlabSquare } from "@fortawesome/free-brands-svg-icons/faGitlabSquare"; +export { definition as faGitter } from "@fortawesome/free-brands-svg-icons/faGitter"; +export { definition as faGlide } from "@fortawesome/free-brands-svg-icons/faGlide"; +export { definition as faGlideG } from "@fortawesome/free-brands-svg-icons/faGlideG"; +export { definition as faGofore } from "@fortawesome/free-brands-svg-icons/faGofore"; +export { definition as faGolang } from "@fortawesome/free-brands-svg-icons/faGolang"; +export { definition as faGoodreads } from "@fortawesome/free-brands-svg-icons/faGoodreads"; +export { definition as faGoodreadsG } from "@fortawesome/free-brands-svg-icons/faGoodreadsG"; +export { definition as faGoogle } from "@fortawesome/free-brands-svg-icons/faGoogle"; +export { definition as faGoogleDrive } from "@fortawesome/free-brands-svg-icons/faGoogleDrive"; +export { definition as faGooglePay } from "@fortawesome/free-brands-svg-icons/faGooglePay"; +export { definition as faGooglePlay } from "@fortawesome/free-brands-svg-icons/faGooglePlay"; +export { definition as faGooglePlus } from "@fortawesome/free-brands-svg-icons/faGooglePlus"; +export { definition as faGooglePlusG } from "@fortawesome/free-brands-svg-icons/faGooglePlusG"; +export { definition as faGooglePlusSquare } from "@fortawesome/free-brands-svg-icons/faGooglePlusSquare"; +export { definition as faGoogleScholar } from "@fortawesome/free-brands-svg-icons/faGoogleScholar"; +export { definition as faGoogleWallet } from "@fortawesome/free-brands-svg-icons/faGoogleWallet"; +export { definition as faGratipay } from "@fortawesome/free-brands-svg-icons/faGratipay"; +export { definition as faGrav } from "@fortawesome/free-brands-svg-icons/faGrav"; +export { definition as faGripfire } from "@fortawesome/free-brands-svg-icons/faGripfire"; +export { definition as faGrunt } from "@fortawesome/free-brands-svg-icons/faGrunt"; +export { definition as faGuilded } from "@fortawesome/free-brands-svg-icons/faGuilded"; +export { definition as faGulp } from "@fortawesome/free-brands-svg-icons/faGulp"; +export { definition as faHackerNews } from "@fortawesome/free-brands-svg-icons/faHackerNews"; +export { definition as faHackerNewsSquare } from "@fortawesome/free-brands-svg-icons/faHackerNewsSquare"; +export { definition as faHackerrank } from "@fortawesome/free-brands-svg-icons/faHackerrank"; +export { definition as faHashnode } from "@fortawesome/free-brands-svg-icons/faHashnode"; +export { definition as faHips } from "@fortawesome/free-brands-svg-icons/faHips"; +export { definition as faHireAHelper } from "@fortawesome/free-brands-svg-icons/faHireAHelper"; +export { definition as faHive } from "@fortawesome/free-brands-svg-icons/faHive"; +export { definition as faHooli } from "@fortawesome/free-brands-svg-icons/faHooli"; +export { definition as faHornbill } from "@fortawesome/free-brands-svg-icons/faHornbill"; +export { definition as faHotjar } from "@fortawesome/free-brands-svg-icons/faHotjar"; +export { definition as faHouzz } from "@fortawesome/free-brands-svg-icons/faHouzz"; +export { definition as faHtml5 } from "@fortawesome/free-brands-svg-icons/faHtml5"; +export { definition as faHubspot } from "@fortawesome/free-brands-svg-icons/faHubspot"; +export { definition as faIdeal } from "@fortawesome/free-brands-svg-icons/faIdeal"; +export { definition as faImdb } from "@fortawesome/free-brands-svg-icons/faImdb"; +export { definition as faInnosoft } from "@fortawesome/free-brands-svg-icons/faInnosoft"; +export { definition as faInstagram } from "@fortawesome/free-brands-svg-icons/faInstagram"; +export { definition as faInstagramSquare } from "@fortawesome/free-brands-svg-icons/faInstagramSquare"; +export { definition as faInstalod } from "@fortawesome/free-brands-svg-icons/faInstalod"; +export { definition as faIntercom } from "@fortawesome/free-brands-svg-icons/faIntercom"; +export { definition as faInternetExplorer } from "@fortawesome/free-brands-svg-icons/faInternetExplorer"; +export { definition as faInvision } from "@fortawesome/free-brands-svg-icons/faInvision"; +export { definition as faIoxhost } from "@fortawesome/free-brands-svg-icons/faIoxhost"; +export { definition as faItchIo } from "@fortawesome/free-brands-svg-icons/faItchIo"; +export { definition as faItunes } from "@fortawesome/free-brands-svg-icons/faItunes"; +export { definition as faItunesNote } from "@fortawesome/free-brands-svg-icons/faItunesNote"; +export { definition as faJava } from "@fortawesome/free-brands-svg-icons/faJava"; +export { definition as faJediOrder } from "@fortawesome/free-brands-svg-icons/faJediOrder"; +export { definition as faJenkins } from "@fortawesome/free-brands-svg-icons/faJenkins"; +export { definition as faJira } from "@fortawesome/free-brands-svg-icons/faJira"; +export { definition as faJoget } from "@fortawesome/free-brands-svg-icons/faJoget"; +export { definition as faJoomla } from "@fortawesome/free-brands-svg-icons/faJoomla"; +export { definition as faJs } from "@fortawesome/free-brands-svg-icons/faJs"; +export { definition as faJsSquare } from "@fortawesome/free-brands-svg-icons/faJsSquare"; +export { definition as faJsfiddle } from "@fortawesome/free-brands-svg-icons/faJsfiddle"; +export { definition as faJxl } from "@fortawesome/free-brands-svg-icons/faJxl"; +export { definition as faKaggle } from "@fortawesome/free-brands-svg-icons/faKaggle"; +export { definition as faKeybase } from "@fortawesome/free-brands-svg-icons/faKeybase"; +export { definition as faKeycdn } from "@fortawesome/free-brands-svg-icons/faKeycdn"; +export { definition as faKickstarter } from "@fortawesome/free-brands-svg-icons/faKickstarter"; +export { definition as faKickstarterK } from "@fortawesome/free-brands-svg-icons/faKickstarterK"; +export { definition as faKorvue } from "@fortawesome/free-brands-svg-icons/faKorvue"; +export { definition as faLaravel } from "@fortawesome/free-brands-svg-icons/faLaravel"; +export { definition as faLastfm } from "@fortawesome/free-brands-svg-icons/faLastfm"; +export { definition as faLastfmSquare } from "@fortawesome/free-brands-svg-icons/faLastfmSquare"; +export { definition as faLeanpub } from "@fortawesome/free-brands-svg-icons/faLeanpub"; +export { definition as faLess } from "@fortawesome/free-brands-svg-icons/faLess"; +export { definition as faLetterboxd } from "@fortawesome/free-brands-svg-icons/faLetterboxd"; +export { definition as faLine } from "@fortawesome/free-brands-svg-icons/faLine"; +export { definition as faLinkedin } from "@fortawesome/free-brands-svg-icons/faLinkedin"; +export { definition as faLinkedinIn } from "@fortawesome/free-brands-svg-icons/faLinkedinIn"; +export { definition as faLinode } from "@fortawesome/free-brands-svg-icons/faLinode"; +export { definition as faLinux } from "@fortawesome/free-brands-svg-icons/faLinux"; +export { definition as faLyft } from "@fortawesome/free-brands-svg-icons/faLyft"; +export { definition as faMagento } from "@fortawesome/free-brands-svg-icons/faMagento"; +export { definition as faMailchimp } from "@fortawesome/free-brands-svg-icons/faMailchimp"; +export { definition as faMandalorian } from "@fortawesome/free-brands-svg-icons/faMandalorian"; +export { definition as faMarkdown } from "@fortawesome/free-brands-svg-icons/faMarkdown"; +export { definition as faMastodon } from "@fortawesome/free-brands-svg-icons/faMastodon"; +export { definition as faMaxcdn } from "@fortawesome/free-brands-svg-icons/faMaxcdn"; +export { definition as faMdb } from "@fortawesome/free-brands-svg-icons/faMdb"; +export { definition as faMedapps } from "@fortawesome/free-brands-svg-icons/faMedapps"; +export { definition as faMedium } from "@fortawesome/free-brands-svg-icons/faMedium"; +export { definition as faMediumM } from "@fortawesome/free-brands-svg-icons/faMediumM"; +export { definition as faMedrt } from "@fortawesome/free-brands-svg-icons/faMedrt"; +export { definition as faMeetup } from "@fortawesome/free-brands-svg-icons/faMeetup"; +export { definition as faMegaport } from "@fortawesome/free-brands-svg-icons/faMegaport"; +export { definition as faMendeley } from "@fortawesome/free-brands-svg-icons/faMendeley"; +export { definition as faMeta } from "@fortawesome/free-brands-svg-icons/faMeta"; +export { definition as faMicroblog } from "@fortawesome/free-brands-svg-icons/faMicroblog"; +export { definition as faMicrosoft } from "@fortawesome/free-brands-svg-icons/faMicrosoft"; +export { definition as faMintbit } from "@fortawesome/free-brands-svg-icons/faMintbit"; +export { definition as faMix } from "@fortawesome/free-brands-svg-icons/faMix"; +export { definition as faMixcloud } from "@fortawesome/free-brands-svg-icons/faMixcloud"; +export { definition as faMixer } from "@fortawesome/free-brands-svg-icons/faMixer"; +export { definition as faMizuni } from "@fortawesome/free-brands-svg-icons/faMizuni"; +export { definition as faModx } from "@fortawesome/free-brands-svg-icons/faModx"; +export { definition as faMonero } from "@fortawesome/free-brands-svg-icons/faMonero"; +export { definition as faNapster } from "@fortawesome/free-brands-svg-icons/faNapster"; +export { definition as faNeos } from "@fortawesome/free-brands-svg-icons/faNeos"; +export { definition as faNfcDirectional } from "@fortawesome/free-brands-svg-icons/faNfcDirectional"; +export { definition as faNfcSymbol } from "@fortawesome/free-brands-svg-icons/faNfcSymbol"; +export { definition as faNimblr } from "@fortawesome/free-brands-svg-icons/faNimblr"; +export { definition as faNode } from "@fortawesome/free-brands-svg-icons/faNode"; +export { definition as faNodeJs } from "@fortawesome/free-brands-svg-icons/faNodeJs"; +export { definition as faNpm } from "@fortawesome/free-brands-svg-icons/faNpm"; +export { definition as faNs8 } from "@fortawesome/free-brands-svg-icons/faNs8"; +export { definition as faNutritionix } from "@fortawesome/free-brands-svg-icons/faNutritionix"; +export { definition as faOctopusDeploy } from "@fortawesome/free-brands-svg-icons/faOctopusDeploy"; +export { definition as faOdnoklassniki } from "@fortawesome/free-brands-svg-icons/faOdnoklassniki"; +export { definition as faOdnoklassnikiSquare } from "@fortawesome/free-brands-svg-icons/faOdnoklassnikiSquare"; +export { definition as faOdysee } from "@fortawesome/free-brands-svg-icons/faOdysee"; +export { definition as faOldRepublic } from "@fortawesome/free-brands-svg-icons/faOldRepublic"; +export { definition as faOpencart } from "@fortawesome/free-brands-svg-icons/faOpencart"; +export { definition as faOpenid } from "@fortawesome/free-brands-svg-icons/faOpenid"; +export { definition as faOpensuse } from "@fortawesome/free-brands-svg-icons/faOpensuse"; +export { definition as faOpera } from "@fortawesome/free-brands-svg-icons/faOpera"; +export { definition as faOptinMonster } from "@fortawesome/free-brands-svg-icons/faOptinMonster"; +export { definition as faOrcid } from "@fortawesome/free-brands-svg-icons/faOrcid"; +export { definition as faOsi } from "@fortawesome/free-brands-svg-icons/faOsi"; +export { definition as faPadlet } from "@fortawesome/free-brands-svg-icons/faPadlet"; +export { definition as faPage4 } from "@fortawesome/free-brands-svg-icons/faPage4"; +export { definition as faPagelines } from "@fortawesome/free-brands-svg-icons/faPagelines"; +export { definition as faPalfed } from "@fortawesome/free-brands-svg-icons/faPalfed"; +export { definition as faPatreon } from "@fortawesome/free-brands-svg-icons/faPatreon"; +export { definition as faPaypal } from "@fortawesome/free-brands-svg-icons/faPaypal"; +export { definition as faPerbyte } from "@fortawesome/free-brands-svg-icons/faPerbyte"; +export { definition as faPeriscope } from "@fortawesome/free-brands-svg-icons/faPeriscope"; +export { definition as faPhabricator } from "@fortawesome/free-brands-svg-icons/faPhabricator"; +export { definition as faPhoenixFramework } from "@fortawesome/free-brands-svg-icons/faPhoenixFramework"; +export { definition as faPhoenixSquadron } from "@fortawesome/free-brands-svg-icons/faPhoenixSquadron"; +export { definition as faPhp } from "@fortawesome/free-brands-svg-icons/faPhp"; +export { definition as faPiedPiper } from "@fortawesome/free-brands-svg-icons/faPiedPiper"; +export { definition as faPiedPiperAlt } from "@fortawesome/free-brands-svg-icons/faPiedPiperAlt"; +export { definition as faPiedPiperHat } from "@fortawesome/free-brands-svg-icons/faPiedPiperHat"; +export { definition as faPiedPiperPp } from "@fortawesome/free-brands-svg-icons/faPiedPiperPp"; +export { definition as faPiedPiperSquare } from "@fortawesome/free-brands-svg-icons/faPiedPiperSquare"; +export { definition as faPinterest } from "@fortawesome/free-brands-svg-icons/faPinterest"; +export { definition as faPinterestP } from "@fortawesome/free-brands-svg-icons/faPinterestP"; +export { definition as faPinterestSquare } from "@fortawesome/free-brands-svg-icons/faPinterestSquare"; +export { definition as faPix } from "@fortawesome/free-brands-svg-icons/faPix"; +export { definition as faPixiv } from "@fortawesome/free-brands-svg-icons/faPixiv"; +export { definition as faPlaystation } from "@fortawesome/free-brands-svg-icons/faPlaystation"; +export { definition as faProductHunt } from "@fortawesome/free-brands-svg-icons/faProductHunt"; +export { definition as faPushed } from "@fortawesome/free-brands-svg-icons/faPushed"; +export { definition as faPython } from "@fortawesome/free-brands-svg-icons/faPython"; +export { definition as faQq } from "@fortawesome/free-brands-svg-icons/faQq"; +export { definition as faQuinscape } from "@fortawesome/free-brands-svg-icons/faQuinscape"; +export { definition as faQuora } from "@fortawesome/free-brands-svg-icons/faQuora"; +export { definition as faRProject } from "@fortawesome/free-brands-svg-icons/faRProject"; +export { definition as faRaspberryPi } from "@fortawesome/free-brands-svg-icons/faRaspberryPi"; +export { definition as faRavelry } from "@fortawesome/free-brands-svg-icons/faRavelry"; +export { definition as faReact } from "@fortawesome/free-brands-svg-icons/faReact"; +export { definition as faReacteurope } from "@fortawesome/free-brands-svg-icons/faReacteurope"; +export { definition as faReadme } from "@fortawesome/free-brands-svg-icons/faReadme"; +export { definition as faRebel } from "@fortawesome/free-brands-svg-icons/faRebel"; +export { definition as faRedRiver } from "@fortawesome/free-brands-svg-icons/faRedRiver"; +export { definition as faReddit } from "@fortawesome/free-brands-svg-icons/faReddit"; +export { definition as faRedditAlien } from "@fortawesome/free-brands-svg-icons/faRedditAlien"; +export { definition as faRedditSquare } from "@fortawesome/free-brands-svg-icons/faRedditSquare"; +export { definition as faRedhat } from "@fortawesome/free-brands-svg-icons/faRedhat"; +export { definition as faRendact } from "@fortawesome/free-brands-svg-icons/faRendact"; +export { definition as faRenren } from "@fortawesome/free-brands-svg-icons/faRenren"; +export { definition as faReplyd } from "@fortawesome/free-brands-svg-icons/faReplyd"; +export { definition as faResearchgate } from "@fortawesome/free-brands-svg-icons/faResearchgate"; +export { definition as faResolving } from "@fortawesome/free-brands-svg-icons/faResolving"; +export { definition as faRev } from "@fortawesome/free-brands-svg-icons/faRev"; +export { definition as faRocketchat } from "@fortawesome/free-brands-svg-icons/faRocketchat"; +export { definition as faRockrms } from "@fortawesome/free-brands-svg-icons/faRockrms"; +export { definition as faRust } from "@fortawesome/free-brands-svg-icons/faRust"; +export { definition as faSafari } from "@fortawesome/free-brands-svg-icons/faSafari"; +export { definition as faSalesforce } from "@fortawesome/free-brands-svg-icons/faSalesforce"; +export { definition as faSass } from "@fortawesome/free-brands-svg-icons/faSass"; +export { definition as faSchlix } from "@fortawesome/free-brands-svg-icons/faSchlix"; +export { definition as faScreenpal } from "@fortawesome/free-brands-svg-icons/faScreenpal"; +export { definition as faScribd } from "@fortawesome/free-brands-svg-icons/faScribd"; +export { definition as faSearchengin } from "@fortawesome/free-brands-svg-icons/faSearchengin"; +export { definition as faSellcast } from "@fortawesome/free-brands-svg-icons/faSellcast"; +export { definition as faSellsy } from "@fortawesome/free-brands-svg-icons/faSellsy"; +export { definition as faServicestack } from "@fortawesome/free-brands-svg-icons/faServicestack"; +export { definition as faShirtsinbulk } from "@fortawesome/free-brands-svg-icons/faShirtsinbulk"; +export { definition as faShoelace } from "@fortawesome/free-brands-svg-icons/faShoelace"; +export { definition as faShopify } from "@fortawesome/free-brands-svg-icons/faShopify"; +export { definition as faShopware } from "@fortawesome/free-brands-svg-icons/faShopware"; +export { definition as faSignalMessenger } from "@fortawesome/free-brands-svg-icons/faSignalMessenger"; +export { definition as faSimplybuilt } from "@fortawesome/free-brands-svg-icons/faSimplybuilt"; +export { definition as faSistrix } from "@fortawesome/free-brands-svg-icons/faSistrix"; +export { definition as faSith } from "@fortawesome/free-brands-svg-icons/faSith"; +export { definition as faSitrox } from "@fortawesome/free-brands-svg-icons/faSitrox"; +export { definition as faSketch } from "@fortawesome/free-brands-svg-icons/faSketch"; +export { definition as faSkyatlas } from "@fortawesome/free-brands-svg-icons/faSkyatlas"; +export { definition as faSkype } from "@fortawesome/free-brands-svg-icons/faSkype"; +export { definition as faSlack } from "@fortawesome/free-brands-svg-icons/faSlack"; +export { definition as faSlackHash } from "@fortawesome/free-brands-svg-icons/faSlackHash"; +export { definition as faSlideshare } from "@fortawesome/free-brands-svg-icons/faSlideshare"; +export { definition as faSnapchat } from "@fortawesome/free-brands-svg-icons/faSnapchat"; +export { definition as faSnapchatGhost } from "@fortawesome/free-brands-svg-icons/faSnapchatGhost"; +export { definition as faSnapchatSquare } from "@fortawesome/free-brands-svg-icons/faSnapchatSquare"; +export { definition as faSoundcloud } from "@fortawesome/free-brands-svg-icons/faSoundcloud"; +export { definition as faSourcetree } from "@fortawesome/free-brands-svg-icons/faSourcetree"; +export { definition as faSpaceAwesome } from "@fortawesome/free-brands-svg-icons/faSpaceAwesome"; +export { definition as faSpeakap } from "@fortawesome/free-brands-svg-icons/faSpeakap"; +export { definition as faSpeakerDeck } from "@fortawesome/free-brands-svg-icons/faSpeakerDeck"; +export { definition as faSpotify } from "@fortawesome/free-brands-svg-icons/faSpotify"; +export { definition as faSquareBehance } from "@fortawesome/free-brands-svg-icons/faSquareBehance"; +export { definition as faSquareBluesky } from "@fortawesome/free-brands-svg-icons/faSquareBluesky"; +export { definition as faSquareDribbble } from "@fortawesome/free-brands-svg-icons/faSquareDribbble"; +export { definition as faSquareFacebook } from "@fortawesome/free-brands-svg-icons/faSquareFacebook"; +export { definition as faSquareFontAwesome } from "@fortawesome/free-brands-svg-icons/faSquareFontAwesome"; +export { definition as faSquareFontAwesomeStroke } from "@fortawesome/free-brands-svg-icons/faSquareFontAwesomeStroke"; +export { definition as faSquareGit } from "@fortawesome/free-brands-svg-icons/faSquareGit"; +export { definition as faSquareGithub } from "@fortawesome/free-brands-svg-icons/faSquareGithub"; +export { definition as faSquareGitlab } from "@fortawesome/free-brands-svg-icons/faSquareGitlab"; +export { definition as faSquareGooglePlus } from "@fortawesome/free-brands-svg-icons/faSquareGooglePlus"; +export { definition as faSquareHackerNews } from "@fortawesome/free-brands-svg-icons/faSquareHackerNews"; +export { definition as faSquareInstagram } from "@fortawesome/free-brands-svg-icons/faSquareInstagram"; +export { definition as faSquareJs } from "@fortawesome/free-brands-svg-icons/faSquareJs"; +export { definition as faSquareKickstarter } from "@fortawesome/free-brands-svg-icons/faSquareKickstarter"; +export { definition as faSquareLastfm } from "@fortawesome/free-brands-svg-icons/faSquareLastfm"; +export { definition as faSquareLetterboxd } from "@fortawesome/free-brands-svg-icons/faSquareLetterboxd"; +export { definition as faSquareOdnoklassniki } from "@fortawesome/free-brands-svg-icons/faSquareOdnoklassniki"; +export { definition as faSquarePiedPiper } from "@fortawesome/free-brands-svg-icons/faSquarePiedPiper"; +export { definition as faSquarePinterest } from "@fortawesome/free-brands-svg-icons/faSquarePinterest"; +export { definition as faSquareReddit } from "@fortawesome/free-brands-svg-icons/faSquareReddit"; +export { definition as faSquareSnapchat } from "@fortawesome/free-brands-svg-icons/faSquareSnapchat"; +export { definition as faSquareSteam } from "@fortawesome/free-brands-svg-icons/faSquareSteam"; +export { definition as faSquareThreads } from "@fortawesome/free-brands-svg-icons/faSquareThreads"; +export { definition as faSquareTumblr } from "@fortawesome/free-brands-svg-icons/faSquareTumblr"; +export { definition as faSquareTwitter } from "@fortawesome/free-brands-svg-icons/faSquareTwitter"; +export { definition as faSquareUpwork } from "@fortawesome/free-brands-svg-icons/faSquareUpwork"; +export { definition as faSquareViadeo } from "@fortawesome/free-brands-svg-icons/faSquareViadeo"; +export { definition as faSquareVimeo } from "@fortawesome/free-brands-svg-icons/faSquareVimeo"; +export { definition as faSquareWebAwesome } from "@fortawesome/free-brands-svg-icons/faSquareWebAwesome"; +export { definition as faSquareWebAwesomeStroke } from "@fortawesome/free-brands-svg-icons/faSquareWebAwesomeStroke"; +export { definition as faSquareWhatsapp } from "@fortawesome/free-brands-svg-icons/faSquareWhatsapp"; +export { definition as faSquareXTwitter } from "@fortawesome/free-brands-svg-icons/faSquareXTwitter"; +export { definition as faSquareXing } from "@fortawesome/free-brands-svg-icons/faSquareXing"; +export { definition as faSquareYoutube } from "@fortawesome/free-brands-svg-icons/faSquareYoutube"; +export { definition as faSquarespace } from "@fortawesome/free-brands-svg-icons/faSquarespace"; +export { definition as faStackExchange } from "@fortawesome/free-brands-svg-icons/faStackExchange"; +export { definition as faStackOverflow } from "@fortawesome/free-brands-svg-icons/faStackOverflow"; +export { definition as faStackpath } from "@fortawesome/free-brands-svg-icons/faStackpath"; +export { definition as faStaylinked } from "@fortawesome/free-brands-svg-icons/faStaylinked"; +export { definition as faSteam } from "@fortawesome/free-brands-svg-icons/faSteam"; +export { definition as faSteamSquare } from "@fortawesome/free-brands-svg-icons/faSteamSquare"; +export { definition as faSteamSymbol } from "@fortawesome/free-brands-svg-icons/faSteamSymbol"; +export { definition as faStickerMule } from "@fortawesome/free-brands-svg-icons/faStickerMule"; +export { definition as faStrava } from "@fortawesome/free-brands-svg-icons/faStrava"; +export { definition as faStripe } from "@fortawesome/free-brands-svg-icons/faStripe"; +export { definition as faStripeS } from "@fortawesome/free-brands-svg-icons/faStripeS"; +export { definition as faStubber } from "@fortawesome/free-brands-svg-icons/faStubber"; +export { definition as faStudiovinari } from "@fortawesome/free-brands-svg-icons/faStudiovinari"; +export { definition as faStumbleupon } from "@fortawesome/free-brands-svg-icons/faStumbleupon"; +export { definition as faStumbleuponCircle } from "@fortawesome/free-brands-svg-icons/faStumbleuponCircle"; +export { definition as faSuperpowers } from "@fortawesome/free-brands-svg-icons/faSuperpowers"; +export { definition as faSupple } from "@fortawesome/free-brands-svg-icons/faSupple"; +export { definition as faSuse } from "@fortawesome/free-brands-svg-icons/faSuse"; +export { definition as faSwift } from "@fortawesome/free-brands-svg-icons/faSwift"; +export { definition as faSymfony } from "@fortawesome/free-brands-svg-icons/faSymfony"; +export { definition as faTeamspeak } from "@fortawesome/free-brands-svg-icons/faTeamspeak"; +export { definition as faTelegram } from "@fortawesome/free-brands-svg-icons/faTelegram"; +export { definition as faTelegramPlane } from "@fortawesome/free-brands-svg-icons/faTelegramPlane"; +export { definition as faTencentWeibo } from "@fortawesome/free-brands-svg-icons/faTencentWeibo"; +export { definition as faTheRedYeti } from "@fortawesome/free-brands-svg-icons/faTheRedYeti"; +export { definition as faThemeco } from "@fortawesome/free-brands-svg-icons/faThemeco"; +export { definition as faThemeisle } from "@fortawesome/free-brands-svg-icons/faThemeisle"; +export { definition as faThinkPeaks } from "@fortawesome/free-brands-svg-icons/faThinkPeaks"; +export { definition as faThreads } from "@fortawesome/free-brands-svg-icons/faThreads"; +export { definition as faTiktok } from "@fortawesome/free-brands-svg-icons/faTiktok"; +export { definition as faTradeFederation } from "@fortawesome/free-brands-svg-icons/faTradeFederation"; +export { definition as faTrello } from "@fortawesome/free-brands-svg-icons/faTrello"; +export { definition as faTumblr } from "@fortawesome/free-brands-svg-icons/faTumblr"; +export { definition as faTumblrSquare } from "@fortawesome/free-brands-svg-icons/faTumblrSquare"; +export { definition as faTwitch } from "@fortawesome/free-brands-svg-icons/faTwitch"; +export { definition as faTwitter } from "@fortawesome/free-brands-svg-icons/faTwitter"; +export { definition as faTwitterSquare } from "@fortawesome/free-brands-svg-icons/faTwitterSquare"; +export { definition as faTypo3 } from "@fortawesome/free-brands-svg-icons/faTypo3"; +export { definition as faUber } from "@fortawesome/free-brands-svg-icons/faUber"; +export { definition as faUbuntu } from "@fortawesome/free-brands-svg-icons/faUbuntu"; +export { definition as faUikit } from "@fortawesome/free-brands-svg-icons/faUikit"; +export { definition as faUmbraco } from "@fortawesome/free-brands-svg-icons/faUmbraco"; +export { definition as faUncharted } from "@fortawesome/free-brands-svg-icons/faUncharted"; +export { definition as faUniregistry } from "@fortawesome/free-brands-svg-icons/faUniregistry"; +export { definition as faUnity } from "@fortawesome/free-brands-svg-icons/faUnity"; +export { definition as faUnsplash } from "@fortawesome/free-brands-svg-icons/faUnsplash"; +export { definition as faUntappd } from "@fortawesome/free-brands-svg-icons/faUntappd"; +export { definition as faUps } from "@fortawesome/free-brands-svg-icons/faUps"; +export { definition as faUpwork } from "@fortawesome/free-brands-svg-icons/faUpwork"; +export { definition as faUsb } from "@fortawesome/free-brands-svg-icons/faUsb"; +export { definition as faUsps } from "@fortawesome/free-brands-svg-icons/faUsps"; +export { definition as faUssunnah } from "@fortawesome/free-brands-svg-icons/faUssunnah"; +export { definition as faVaadin } from "@fortawesome/free-brands-svg-icons/faVaadin"; +export { definition as faViacoin } from "@fortawesome/free-brands-svg-icons/faViacoin"; +export { definition as faViadeo } from "@fortawesome/free-brands-svg-icons/faViadeo"; +export { definition as faViadeoSquare } from "@fortawesome/free-brands-svg-icons/faViadeoSquare"; +export { definition as faViber } from "@fortawesome/free-brands-svg-icons/faViber"; +export { definition as faVimeo } from "@fortawesome/free-brands-svg-icons/faVimeo"; +export { definition as faVimeoSquare } from "@fortawesome/free-brands-svg-icons/faVimeoSquare"; +export { definition as faVimeoV } from "@fortawesome/free-brands-svg-icons/faVimeoV"; +export { definition as faVine } from "@fortawesome/free-brands-svg-icons/faVine"; +export { definition as faVk } from "@fortawesome/free-brands-svg-icons/faVk"; +export { definition as faVnv } from "@fortawesome/free-brands-svg-icons/faVnv"; +export { definition as faVuejs } from "@fortawesome/free-brands-svg-icons/faVuejs"; +export { definition as faWatchmanMonitoring } from "@fortawesome/free-brands-svg-icons/faWatchmanMonitoring"; +export { definition as faWaze } from "@fortawesome/free-brands-svg-icons/faWaze"; +export { definition as faWebflow } from "@fortawesome/free-brands-svg-icons/faWebflow"; +export { definition as faWeebly } from "@fortawesome/free-brands-svg-icons/faWeebly"; +export { definition as faWeibo } from "@fortawesome/free-brands-svg-icons/faWeibo"; +export { definition as faWeixin } from "@fortawesome/free-brands-svg-icons/faWeixin"; +export { definition as faWhatsapp } from "@fortawesome/free-brands-svg-icons/faWhatsapp"; +export { definition as faWhatsappSquare } from "@fortawesome/free-brands-svg-icons/faWhatsappSquare"; +export { definition as faWhmcs } from "@fortawesome/free-brands-svg-icons/faWhmcs"; +export { definition as faWikipediaW } from "@fortawesome/free-brands-svg-icons/faWikipediaW"; +export { definition as faWindows } from "@fortawesome/free-brands-svg-icons/faWindows"; +export { definition as faWirsindhandwerk } from "@fortawesome/free-brands-svg-icons/faWirsindhandwerk"; +export { definition as faWix } from "@fortawesome/free-brands-svg-icons/faWix"; +export { definition as faWizardsOfTheCoast } from "@fortawesome/free-brands-svg-icons/faWizardsOfTheCoast"; +export { definition as faWodu } from "@fortawesome/free-brands-svg-icons/faWodu"; +export { definition as faWolfPackBattalion } from "@fortawesome/free-brands-svg-icons/faWolfPackBattalion"; +export { definition as faWordpress } from "@fortawesome/free-brands-svg-icons/faWordpress"; +export { definition as faWordpressSimple } from "@fortawesome/free-brands-svg-icons/faWordpressSimple"; +export { definition as faWpbeginner } from "@fortawesome/free-brands-svg-icons/faWpbeginner"; +export { definition as faWpexplorer } from "@fortawesome/free-brands-svg-icons/faWpexplorer"; +export { definition as faWpforms } from "@fortawesome/free-brands-svg-icons/faWpforms"; +export { definition as faWpressr } from "@fortawesome/free-brands-svg-icons/faWpressr"; +export { definition as faWsh } from "@fortawesome/free-brands-svg-icons/faWsh"; +export { definition as faXTwitter } from "@fortawesome/free-brands-svg-icons/faXTwitter"; +export { definition as faXbox } from "@fortawesome/free-brands-svg-icons/faXbox"; +export { definition as faXing } from "@fortawesome/free-brands-svg-icons/faXing"; +export { definition as faXingSquare } from "@fortawesome/free-brands-svg-icons/faXingSquare"; +export { definition as faYCombinator } from "@fortawesome/free-brands-svg-icons/faYCombinator"; +export { definition as faYahoo } from "@fortawesome/free-brands-svg-icons/faYahoo"; +export { definition as faYammer } from "@fortawesome/free-brands-svg-icons/faYammer"; +export { definition as faYandex } from "@fortawesome/free-brands-svg-icons/faYandex"; +export { definition as faYandexInternational } from "@fortawesome/free-brands-svg-icons/faYandexInternational"; +export { definition as faYarn } from "@fortawesome/free-brands-svg-icons/faYarn"; +export { definition as faYelp } from "@fortawesome/free-brands-svg-icons/faYelp"; +export { definition as faYoast } from "@fortawesome/free-brands-svg-icons/faYoast"; +export { definition as faYoutube } from "@fortawesome/free-brands-svg-icons/faYoutube"; +export { definition as faYoutubeSquare } from "@fortawesome/free-brands-svg-icons/faYoutubeSquare"; +export { definition as faZhihu } from "@fortawesome/free-brands-svg-icons/faZhihu"; +export { definition as fa00 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as fa100 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as fa360Degrees } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAbacus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAccentGrave } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAcorn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAirConditioner } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAirplay } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlarmClock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlarmExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlarmPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlarmSnooze } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlbum } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlbumCirclePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlbumCircleUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlbumCollection } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlbumCollectionCirclePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlbumCollectionCircleUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlicorn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlien } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlien8bit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlienMonster } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlignSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAmpGuitar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAmpersand } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAnalytics } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAngel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAngle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAngle90 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAnglesUpDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAnt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faApartment } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAperture } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faApostrophe } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAppleCore } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAppleCrate } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltFromBottom } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltFromLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltFromRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltFromTop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltSquareDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltSquareLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltSquareRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltSquareUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltToBottom } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltToLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltToRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltToTop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowAltUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownBigSmall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownFromArc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownFromBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownFromDottedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownFromLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownLeftAndArrowUpRightToCenter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownSmallBig } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownSquareTriangle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownToArc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownToBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownToDottedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownToSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowDownTriangleSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowFromBottom } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowFromLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowFromRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowFromTop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowLeftFromArc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowLeftFromBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowLeftFromLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowLeftLongToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowLeftToArc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowLeftToBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowLeftToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowProgress } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowRightFromArc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowRightFromLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowRightLongToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowRightToArc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowRightToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowSquareDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowSquareLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowSquareRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowSquareUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowToBottom } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowToLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowToRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowToTop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowTurnDownLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowTurnDownRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowTurnLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowTurnLeftDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowTurnLeftUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowTurnRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpBigSmall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpFromArc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpFromDottedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpFromLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpFromSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpLeftFromCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpRightAndArrowDownLeftFromCenter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpSmallBig } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpSquareTriangle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpToArc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpToBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpToDottedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowUpTriangleSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsCross } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsFromDottedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsFromLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsMaximize } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsMinimize } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsRepeat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsRepeat1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsRetweet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsRotateReverse } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsToDottedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faArrowsToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAtomAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAtomSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAudioDescriptionSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAvocado } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAwardSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAxe } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faAxeBattle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBackpack } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBadge } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBadgeCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBadgeDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBadgePercent } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBadgeSheriff } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBadgerHoney } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBadminton } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBagSeedling } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBagShoppingMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBagShoppingPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBagel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBagsShopping } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBaguette } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBallPile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBalloon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBalloons } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBallot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBallotCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBanBug } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBanParking } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBanana } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBanjo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBarcodeAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBarcodeRead } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBarcodeScan } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBarnSilo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBarsFilter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBarsSort } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBasketShoppingMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBasketShoppingPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBasketShoppingSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBasketballHoop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBattery1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBatteryBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBatteryExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBatteryLow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBatterySlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBedAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBedBunk } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBedEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBedFront } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBee } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBeerFoam } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBeerMug } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBellExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBellOn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBellPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBellRing } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBellSchool } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBellSchoolSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBells } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBenchTree } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBetamax } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBikingMountain } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBillboard } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBinBottles } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBinBottlesRecycle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBinRecycle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBinary } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBinaryCircleCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBinaryLock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBinarySlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBird } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlanket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlanketFire } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlinds } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlindsOpen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlindsRaised } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlockBrick } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlockBrickFire } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlockQuestion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlockQuote } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBlueberries } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoltAuto } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoltSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoneBreak } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookArrowRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookBlank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookCircleArrowRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookCircleArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookCopy } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookFont } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookLaw } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookOpenAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookOpenCover } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookSection } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookSparkles } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookSpells } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookmarkCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBookmarkSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBooks } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBooksMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoombox } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBootHeeled } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoothCurtain } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBorderBottom } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBorderBottomRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBorderCenterH } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBorderCenterV } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBorderInner } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBorderLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBorderOuter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBorderRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBorderStyleAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBorderTop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBottleBaby } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowArrow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlChopsticks } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlChopsticksNoodles } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlHot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlSalad } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlScoop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlScoops } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlShavedIce } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlSoftServe } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlSpoon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlingBallPin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBowlingPins } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxBallot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxCircleCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxFragile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxFull } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxOpenFull } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxTaped } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxUsd } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBoxingGlove } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketCurly } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketCurlyLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketCurlyRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketRound } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketRoundRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketSquareRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBrackets } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketsCurly } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketsRound } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBracketsSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBrainArrowCurvedRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBrainCircuit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBrakeWarning } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBreadLoaf } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBreadSliceButter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBridgeSuspension } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBriefcaseArrowRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBriefcaseBlank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBrightness } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBrightnessLow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBringForward } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBringFront } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBroccoli } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBroomWide } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBrowser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBrowsers } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBuildingMagnifyingGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBuildingMemo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBuildings } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBulldozer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBullseyeArrow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBullseyePointer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBuoy } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBuoyMooring } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBurgerCheese } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBurgerFries } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBurgerGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBurgerLettuce } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBurgerSoda } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBurrito } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBusSchool } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faBusinessFront } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faButter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCabin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCabinetFiling } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCactus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCaduceus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCakeSlice } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalculatorAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalculatorSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarCircleExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarCircleMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarCirclePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarCircleUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarClock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarDownload } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarEdit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarImage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarLines } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarLinesPen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarNote } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarPen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarRange } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarStar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarTime } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarUpload } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendarUsers } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCalendars } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCamcorder } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCameraCctv } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCameraCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCameraHome } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCameraMovie } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCameraPolaroid } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCameraSecurity } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCameraSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCameraViewfinder } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCameraWeb } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCameraWebSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCampfire } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCanFood } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCandleHolder } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCandy } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCandyBar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCandyCorn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCannon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarBuilding } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarBump } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarBus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarCircleBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarGarage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarMechanic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarMirrors } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarSideBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarTilt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarWash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCarWrench } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCaravanAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCaravanSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCardClub } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCardDiamond } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCardHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCardSpade } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCards } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCardsBlank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCaretCircleDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCaretCircleLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCaretCircleRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCaretCircleUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCars } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartCircleArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartCircleArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartCircleCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartCircleExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartCirclePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartCircleXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartFlatbedBoxes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartFlatbedEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartShoppingFast } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCartXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCassetteBetamax } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCassetteTape } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCassetteVhs } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCastle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCatSpace } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCauldron } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCctv } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChainHorizontal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChainHorizontalSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChairOffice } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChampagneGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartBullet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartCandlestick } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartKanban } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartLineDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartLineUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartLineUpDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartMixed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartMixedUpCircleCurrency } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartMixedUpCircleDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartNetwork } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartPieAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartPieSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartPieSimpleCircleCurrency } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartPieSimpleCircleDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartPyramid } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartRadar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartScatter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartScatter3d } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartScatterBubble } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartSimpleHorizontal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartTreeMap } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChartWaterfall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCheeseSwiss } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCheeseburger } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCherries } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessBishopAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessBishopPiece } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessClock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessClockAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessClockFlip } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessKingAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessKingPiece } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessKnightAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessKnightPiece } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessPawnAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessPawnPiece } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessQueenAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessQueenPiece } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessRookAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChessRookPiece } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChestnut } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronDoubleDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronDoubleLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronDoubleRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronDoubleUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronSquareDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronSquareLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronSquareRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronSquareUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronsDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronsLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronsRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChevronsUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChfSign } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChimney } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChocolateBar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faChopsticks } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircle0 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircle1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircle2 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircle3 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircle4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircle5 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircle6 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircle7 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircle8 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircle9 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleA } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleAmpersand } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleArrowDownLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleArrowDownRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleArrowUpLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleArrowUpRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleB } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleBookOpen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleBookmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleC } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleCalendar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleCamera } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleCaretDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleCaretLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleCaretRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleCaretUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleD } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleDashed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleDivide } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleDownLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleDownRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleE } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleEllipsis } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleEllipsisVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleEnvelope } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleEuro } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleExclamationCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleF } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleG } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleGf } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleHalf } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleI } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleJ } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleK } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleL } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleLocationArrow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleM } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleMicrophone } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleMicrophoneLines } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleN } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleO } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleP } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleParking } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCirclePhone } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCirclePhoneFlip } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCirclePhoneHangup } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleQ } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleQuarter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleQuarterStroke } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleQuarters } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleR } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleS } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleSmall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleSort } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleSortDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleSortUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleStar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleSterling } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleT } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleThreeQuarters } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleThreeQuartersStroke } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleTrash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleU } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleUpLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleUpRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleV } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleVideo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleW } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleWaveformLines } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleWifi } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleWifiCircleWifi } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleWifiGroup } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleX } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleY } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleYen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCircleZ } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCirclesOverlap } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCitrus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCitrusSlice } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClapperboardPlay } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClarinet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClawMarks } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClipboardListCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClipboardMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClipboardPrescription } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockDesk } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockEight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockEightThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockEleven } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockElevenThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockFive } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockFiveThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockFourThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockNine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockNineThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockOne } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockOneThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockSeven } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockSevenThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockSix } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockSixThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockTen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockTenThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockThree } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockThreeThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockTwelve } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockTwelveThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockTwo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClockTwoThirty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClosedCaptioningSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClothesHanger } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudBinary } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudBoltMoon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudBoltSun } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudDrizzle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudFog } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudHail } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudHailMixed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudQuestion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudRainbow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudShowers } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudSleet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudSnow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudWord } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClouds } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudsMoon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCloudsSun } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faClub } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoconut } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCodePullRequestClosed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCodePullRequestDraft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCodeSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoffeeBean } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoffeeBeans } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoffeePot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoffeeTogo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoffin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoffinCross } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoinBlank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoinFront } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCoinVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faColon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faColumns3 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faComet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faComma } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommand } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltCaptions } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltDots } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltEdit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltImage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltLines } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltQuote } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltSmile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltText } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentAltTimes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentArrowUpRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentCaptions } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentCode } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentEdit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentImage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentLines } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentMiddle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentMiddleAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentMiddleTop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentMiddleTopAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentPen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentQuestion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentQuote } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentSmile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentText } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentTimes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentsAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentsAltDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentsQuestion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCommentsQuestionCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCompassSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCompressArrows } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCompressWide } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faComputerClassic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faComputerMouseScrollwheel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faComputerSpeaker } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faConstruction } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faContainerStorage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faConveyorBelt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faConveyorBeltAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faConveyorBeltArm } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faConveyorBeltBoxes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faConveyorBeltEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCorn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCorner } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCouchSmall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCourtSport } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCowbell } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCowbellCirclePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCowbellMore } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCrab } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCrateApple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCrateEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCreditCardBlank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCreditCardFront } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCreemee } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCricket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCricketBatBall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCroissant } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCrosshairsSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCrutches } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCrystalBall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCucumber } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCupStraw } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCupStrawSwoosh } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCupTogo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCupcake } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCurling } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCurlingStone } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faCustard } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDagger } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDebug } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDeer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDeerRudolph } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDeleteRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDesktopArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDesktopCode } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDesktopMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDesktopSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDewpoint } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiagramCells } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiagramLeanCanvas } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiagramNested } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiagramPrevious } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiagramSankey } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiagramSubtask } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiagramVenn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDial } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDialHigh } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDialLow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDialMax } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDialMed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDialMedHigh } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDialMedLow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDialMin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDialOff } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiamondExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiamondHalf } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiamondHalfStroke } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiamonds4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiceD10 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiceD12 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiceD4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiceD8 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDinosaur } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiploma } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDiscDrive } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDisplayArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDisplayChartUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDisplayChartUpCircleCurrency } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDisplayChartUpCircleDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDisplayCode } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDisplayMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDisplaySlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDistributeSpacingHorizontal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDistributeSpacingVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDitto } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDoNotEnter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDogLeashed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDollarCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDollarSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDollyEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDollyFlatbedAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDollyFlatbedEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDolphin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDonut } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDoughnut } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDownFromBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDownFromDottedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDownFromLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDownLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDownRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDownToBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDownToDottedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDownToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDrawCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDrawSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDreidel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDrone } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDroneAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDroneFront } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDropletDegree } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDropletPercent } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDrumstick } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDryer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDryerAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDryerHeat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faDuck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEarMuffs } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEclipse } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEclipseAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEggFried } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEggplant } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faElephant } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEllipsisHAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEllipsisStroke } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEllipsisStrokeVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEllipsisVAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEmptySet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEngine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEngineExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEngineWarning } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEnvelopeBadge } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEnvelopeCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEnvelopeDot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEnvelopeOpenDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEnvelopes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEscalator } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faExcavator } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faExclamationSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faExpandArrows } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faExpandWide } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faExplodingHead } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEyeDropperFull } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEyeDropperHalf } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEyeEvil } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faEyes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceAngryHorns } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceAnguished } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceAnxiousSweat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceAstonished } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceAwesome } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceBeamHandOverMouth } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceClouds } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceConfounded } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceConfused } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceCowboyHat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceDiagonalMouth } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceDisappointed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceDisguise } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceDotted } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceDowncastSweat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceDrooling } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceExhaling } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceExplode } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceExpressionless } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceEyesXmarks } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceFearful } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceFrownSlight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceGlasses } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceHandOverMouth } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceHandPeeking } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceHandYawn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceHeadBandage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceHoldingBackTears } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceHushed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceIcicles } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceKissClosedEyes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceLying } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceMask } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceMelting } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceMonocle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceNauseated } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceNoseSteam } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceParty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFacePensive } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFacePersevering } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFacePleading } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFacePouting } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceRaisedEyebrow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceRelieved } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSadSweat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSaluting } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceScream } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceShush } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSleeping } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSleepy } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSmileHalo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSmileHearts } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSmileHorns } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSmilePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSmileRelaxed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSmileTear } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSmileTongue } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSmileUpsideDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSmilingHands } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSmirking } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSpiralEyes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSunglasses } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceSwear } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceThermometer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceThinking } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceTissue } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceTongueMoney } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceTongueSweat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceUnamused } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceViewfinder } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceVomit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceWeary } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceWoozy } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceWorried } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceZany } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFaceZipper } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFalafel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFamily } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFamilyDress } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFamilyPants } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFanTable } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFarm } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFence } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFerrisWheel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFieldHockey } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFieldHockeyStickBall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileAward } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileBinary } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileCad } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileCaretDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileCaretUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileCertificate } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileChartColumn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileChartLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileChartPie } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileCircleInfo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileDashedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileDoc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileEps } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileGif } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileJpg } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileLock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileMagnifyingGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileMov } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileMp3 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileMp4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilePlusMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilePng } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilePpt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileSearch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileSpreadsheet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileSvg } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileTimes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileVector } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileXls } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileXml } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFileZip } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFiles } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilesMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilmAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilmCanister } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilmCannister } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilmSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilmSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilms } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilterList } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilterSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFilters } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFireFlame } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFireHydrant } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFireSmoke } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFireplace } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFirewall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFishBones } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFishCooked } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFishingRod } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlagAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlagPennant } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlagSwallowtail } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlame } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlashlight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlaskGear } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlaskPoison } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlaskPotion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlaskRoundPoison } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlaskRoundPotion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlatbread } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlatbreadStuffed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFloppyDiskCircleArrowRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFloppyDiskCircleXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFloppyDiskPen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFloppyDiskTimes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFloppyDisks } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlower } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlowerDaffodil } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlowerTulip } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlute } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFluxCapacitor } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFlyingDisc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFog } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderBookmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderCog } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderDownload } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderGear } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderGrid } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderImage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderMagnifyingGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderSearch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderTimes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderUpload } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolderXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFolders } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFonduePot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFontCase } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFootballHelmet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFork } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faForkKnife } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faForklift } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFort } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFragile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFrame } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFrenchFries } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFrostyHead } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faFunction } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGalaxy } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGalleryThumbnails } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGameBoard } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGameBoardAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGameBoardSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGameConsoleHandheld } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGameConsoleHandheldCrank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGamepadAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGamepadModern } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGarage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGarageCar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGarageOpen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGarlic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGasPumpSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGaugeCircleBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGaugeCircleMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGaugeCirclePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGaugeLow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGaugeMax } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGaugeMin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGaugeSimpleLow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGaugeSimpleMax } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGaugeSimpleMin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGaveDandy } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGearCode } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGearComplex } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGearComplexCode } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGif } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGiftCard } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGingerbreadMan } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlassChampagne } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlassCitrus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlassEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlassHalf } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlassHalfEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlassHalfFull } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlassWhiskeyRocks } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlassesAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlassesRound } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlobePointer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlobeSnow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlobeStand } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGlobeWifi } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGloveBoxing } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGoalNet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGolfClub } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGolfFlagHole } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGramophone } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrapes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrate } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrateDroplet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrid } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrid2 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrid2Plus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrid3 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrid4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrid5 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGridDividers } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGridHorizontal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGridRound } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGridRound2 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGridRound2Plus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGridRound4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGridRound5 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrill } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrillFire } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGrillHot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGripDots } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGripDotsVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGuitarElectric } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGuitars } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGunSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faGunSquirt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faH1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faH2 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faH3 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faH4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faH5 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faH6 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHammerBrush } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHammerCrash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHammerWar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandBackPointDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandBackPointLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandBackPointRibbon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandBackPointRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandBackPointUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandFingersCrossed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandHoldingBox } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandHoldingCircleDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandHoldingMagic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandHoldingSeedling } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandHoldingSkull } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandHorns } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandLove } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandPointRibbon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandReceiving } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandWave } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandsHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandsHoldingDiamond } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandsHoldingDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandsHoldingHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHandsUsd } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHashtagLock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHatBeach } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHatChef } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHatSanta } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHatWinter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHatWitch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeadSide } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeadSideBrain } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeadSideGear } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeadSideGoggles } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeadSideHeadphones } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeadSideHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeadSideMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeadVr } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeartCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeartHalf } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeartHalfAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeartHalfStroke } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeartRate } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeartSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHeat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHelmetBattle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHexagon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHexagonCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHexagonDivide } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHexagonExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHexagonImage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHexagonMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHexagonPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHexagonVerticalNft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHexagonVerticalNftSlanted } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHexagonXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHighDefinition } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHighlighterLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHockeyMask } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHockeyStickPuck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHockeySticks } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHomeBlank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHomeHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHoneyPot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHoodCloak } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHorizontalRule } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHorseSaddle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHose } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHoseReel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHospitals } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHourglassClock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseBlank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseBuilding } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseChimneyBlank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseChimneyHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseDay } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseFlood } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseLeave } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseNight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHousePersonArrive } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHousePersonDepart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHousePersonLeave } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHousePersonReturn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseReturn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseTree } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseTurret } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseWater } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHouseWindow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHumidity } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHundredPoints } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHydra } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faHyphen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faIceSkate } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faIconsAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faImageLandscape } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faImagePolaroid } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faImagePolaroidUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faImageSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faImageUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faImagesUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInboxArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInboxArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInboxFull } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInboxIn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInboxOut } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInboxes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faIndustryAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faIndustryWindows } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInfoSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInhaler } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInputNumeric } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInputPipe } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInputText } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faIntegral } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInterrobang } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faIntersection } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faInventory } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faIslandTreePalm } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faIslandTropical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faJackOLantern } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faJoystick } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faJug } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faJugBottle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKazoo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKerning } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKeySkeleton } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKeySkeletonLeftRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKeyboardBrightness } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKeyboardBrightnessLow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKeyboardDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKeyboardLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKeynote } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKidneys } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKite } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKiwiFruit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKnife } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faKnifeKitchen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLacrosseStick } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLacrosseStickBall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLambda } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLamp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLampDesk } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLampFloor } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLampStreet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLandmarkMagnifyingGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLandscape } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLaptopArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLaptopBinary } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLaptopMobile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLaptopSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLasso } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLassoSparkles } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLayerGroupMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLayerGroupPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLayerMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLayerPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLeafHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLeafMaple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLeafOak } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLeafyGreen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLeftFromBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLeftFromLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLeftLongToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLeftToBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLeftToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightCeiling } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightEmergency } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightEmergencyOn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightSwitch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightSwitchOff } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightSwitchOn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightbulbCfl } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightbulbCflOn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightbulbDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightbulbExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightbulbExclamationOn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightbulbGear } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightbulbMessage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightbulbOn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightbulbSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLighthouse } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLightsHoliday } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLineColumns } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLineHeight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLinkHorizontal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLinkHorizontalSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLinkSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLinkSimpleSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLips } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faListDropdown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faListMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faListRadio } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faListTimeline } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faListTree } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLoader } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLobster } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationCrosshairsSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationDotSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationPen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationPinSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationQuestion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationSmile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLocationXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLockA } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLockAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLockHashtag } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLockKeyhole } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLockKeyholeOpen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLockOpenAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLollipop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLollypop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLoveseat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLuchador } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faLuchadorMask } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMace } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMagnifyingGlassArrowsRotate } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMagnifyingGlassMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMagnifyingGlassPlay } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMagnifyingGlassWaveform } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMailbox } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMailboxFlagUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMakiRoll } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMakizushi } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMandolin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMango } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faManhole } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerAltSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerEdit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerQuestion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerSmile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerTimes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMapMarkerXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMaskLuchador } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMaskSnorkel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMeat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMegaphone } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMelon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMelonSlice } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMemo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMemoCircleCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMemoCircleInfo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMemoPad } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMerge } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageArrowUpRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageBot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageCaptions } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageCode } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageDots } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageEdit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageImage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageLines } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageMiddle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageMiddleTop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessagePen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessagePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageQuestion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageQuote } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageSmile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageSms } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageText } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageTimes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessageXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessages } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessagesDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessagesQuestion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMessaging } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMeter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMeterBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMeterDroplet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMeterFire } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMicrochipAi } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMicrophoneCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMicrophoneCircleAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMicrophoneStand } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMicrowave } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMindShare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMinusHexagon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMinusLarge } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMinusOctagon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMistletoe } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMobileIphone } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMobileNotch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMobileSignal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMobileSignalOut } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoneyBillSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoneyBillSimpleWave } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoneyBillsAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoneyBillsSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoneyCheckDollarPen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoneyCheckEdit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoneyCheckEditAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoneyCheckPen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoneyFromBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoneySimpleFromBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMonitorHeartRate } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMonitorWaveform } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMonkey } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoonCloud } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoonOverSun } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoonStars } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMoped } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMountains } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMouseAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMouseField } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMp3Player } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMug } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMugMarshmallows } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMugTea } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMugTeaSaucer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMushroom } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMusicAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMusicAltSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMusicMagnifyingGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMusicNote } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMusicNoteSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMusicSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faMustache } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNarwhal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNestingDolls } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNfc } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNfcLock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNfcMagnifyingGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNfcPen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNfcSignal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNfcSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNfcTrash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNigiri } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNose } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNote } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNoteMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNotebook } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faNotes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectExclude } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectIntersect } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectSubtract } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectUnion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectsAlignBottom } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectsAlignCenterHorizontal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectsAlignCenterVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectsAlignLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectsAlignRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectsAlignTop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faObjectsColumn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOctagon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOctagonCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOctagonDivide } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOctagonExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOctagonMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOctagonPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOctagonXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOctopus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOilCanDrip } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOilTemp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOilTemperature } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOlive } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOliveBranch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOmega } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOnion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOption } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOrnament } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOutlet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOven } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faOverline } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPageBreak } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPageCaretDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPageCaretUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPaintBrushAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPaintbrushFine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPaintbrushPencil } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPaletteBoxes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPalletAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPalletBox } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPalletBoxes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPanFood } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPanFrying } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPancakes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPanelEws } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPanelFire } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPaperPlaneAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPaperPlaneTop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPaperclipVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faParagraphLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faParagraphRtl } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faParentheses } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faParenthesis } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faParkingCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faParkingCircleSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faParkingSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPartyBack } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPartyBell } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPartyHorn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPawAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPawClaws } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPawSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeach } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeanut } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeanuts } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeapod } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPear } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPedestal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPegasus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPenAltSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPenCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPenClipSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPenFancySlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPenField } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPenLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPenNibSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPenPaintbrush } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPenSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPenSwirl } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPencilMechanical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPencilPaintbrush } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPencilSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPennant } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeople } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeopleDress } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeopleDressSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeoplePants } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeoplePantsSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeopleSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPepper } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPeriod } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonBikingMountain } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonCarry } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonCarryBox } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonDolly } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonDollyEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonDressFairy } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonDressSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonFairy } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonFromPortal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonPinball } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonRunningFast } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonSeat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonSeatReclined } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonSign } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonSkiJumping } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonSkiLift } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonSledding } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonSnowmobiling } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonToDoor } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPersonToPortal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneArrowDownLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneArrowRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneArrowUpRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneCircleAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneCircleDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneHangup } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneIncoming } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneIntercom } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneLaptop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneMissed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneOffice } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneOutgoing } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhonePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneRotary } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneSquareDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhoneXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPhotoFilmMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPi } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPiano } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPianoKeyboard } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPickaxe } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPickleball } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPie } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPig } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPinata } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPinball } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPineapple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPipe } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPipeCircleCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPipeCollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPipeSection } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPipeSmoking } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPipeValve } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPizza } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlaneAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlaneEngines } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlaneProp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlaneTail } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlaneUpSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlanetMoon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlanetRinged } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlateUtensils } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlayPause } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlusHexagon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlusLarge } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPlusOctagon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPodium } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPodiumStar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPoliceBox } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPollPeople } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPompebled } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPool8Ball } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPopcorn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPopsicle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPortalEnter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPortalExit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPotFood } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPotato } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPrescriptionBottlePill } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPresentation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPresentationScreen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPretzel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPrintMagnifyingGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPrintSearch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPrintSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPro } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faProjector } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPump } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPumpkin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPuzzle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPuzzlePieceAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faPuzzlePieceSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faQuestionSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faQuotes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRabbit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRabbitFast } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRabbitRunning } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRaccoon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRacquet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRadar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRadioAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRadioTuner } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRaindrops } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRam } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRampLoading } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRaygun } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleBarcode } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleCode } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleHd } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleHistory } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleHistoryCirclePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleHistoryCircleUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleLandscape } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectanglePortrait } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectanglePro } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleSd } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleTerminal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleVerticalHistory } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectangleWide } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRectanglesMixed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faReel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faReflectBoth } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faReflectHorizontal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faReflectVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRefrigerator } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRepeat1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRepeat1Alt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRepeatAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faReplyClock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faReplyTime } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRestroomSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRetweetAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRhombus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRightFromLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRightLeftLarge } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRightLongToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRightToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRingDiamond } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRingsWedding } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRobotAstromech } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRocketLaunch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRollerCoaster } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRotateExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRotateReverse } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRouteHighway } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRouteInterstate } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRouter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRows } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRugbyBall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRulerTriangle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faRv } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSack } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSalad } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSaltShaker } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSandwich } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSausage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSaveCircleArrowRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSaveCircleXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSaveTimes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSaxHot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSaxophone } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSaxophoneFire } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScalpel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScalpelLineDashed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScalpelPath } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScanner } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScannerGun } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScannerImage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScannerKeyboard } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScannerTouchscreen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScarecrow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScarf } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScreenUsers } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScreencast } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScreenshot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScribble } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScrollOld } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScrollRibbon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScrubber } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faScythe } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSdCards } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSeal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSealExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSealQuestion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSeatAirline } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSemicolon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSend } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSendBack } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSendBackward } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSensor } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSensorAlert } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSensorCloud } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSensorFire } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSensorOn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSensorSmoke } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSensorTriangleExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShareAll } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSheep } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShelves } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShelvesEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShieldCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShieldCross } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShieldExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShieldKeyhole } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShieldMinus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShieldPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShieldQuartered } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShieldSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShieldTimes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShieldXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShippingTimed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShirtLongSleeve } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShirtRunning } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShirtTankTop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShishKebab } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShoppingBasketAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShortcake } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShovel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShovelSnow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShowerAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShowerDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShredder } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShutters } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faShuttlecock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSickle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSidebar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSidebarFlip } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSigma } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignPost } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignPosts } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignPostsWrench } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignal1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignal2 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignal3 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignal4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalAlt1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalAlt2 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalAlt3 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalAlt4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalAltSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalBars } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalBarsFair } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalBarsGood } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalBarsSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalBarsStrong } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalBarsWeak } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalFair } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalGood } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalStream } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalStreamSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalStrong } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignalWeak } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignatureLock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSignatureSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSimCards } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSiren } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSirenOn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSkeleton } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSkeletonRibs } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSkiBoot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSkiBootSki } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSkiJump } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSkiLift } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSkullCow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSlashBack } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSlashForward } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSledding } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSlider } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSlidersHSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSlidersSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSlidersUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSlidersV } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSlidersVSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSlotMachine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSmilePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSmoke } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSnake } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSnooze } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSnowBlowing } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSnowflakeDroplets } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSnowflakes } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSnowmanHead } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSnowmobile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSoftServe } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSolarSystem } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortCircleDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortCircleUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortShapesDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortShapesDownAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortShapesUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortShapesUpAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortSizeDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortSizeDownAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortSizeUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortSizeUpAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSortUpDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSoup } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSpaceStationMoon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSpaceStationMoonAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSpaceStationMoonConstruction } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSpade } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSparkle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSparkles } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSpeaker } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSpeakers } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSpiderBlackWidow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSpiderWeb } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSpinnerScale } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSpinnerThird } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSplit } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSportsball } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSprinkler } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSprinklerCeiling } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquare0 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquare1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquare2 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquare3 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquare4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquare5 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquare6 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquare7 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquare8 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquare9 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareA } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareALock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareAmpersand } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareArrowDownLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareArrowDownRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareArrowLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareArrowRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareArrowUpLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareB } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareC } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareChevronDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareChevronLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareChevronRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareChevronUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareCode } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareD } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareDashed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareDashedCirclePlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareDivide } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareDollar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareDownLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareDownRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareE } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareEllipsis } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareEllipsisVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareF } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareFragile } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareG } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareHeart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareI } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareInfo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareJ } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareK } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareKanban } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareL } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareList } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareM } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareN } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareO } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareP } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareParkingSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquarePhoneHangup } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareQ } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareQuarters } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareQuestion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareQuote } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareR } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareRing } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareRoot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareS } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareSliders } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareSlidersVertical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareSmall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareStar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareT } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareTerminal } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareThisWayUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareU } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareUpLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareUser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareV } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareW } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareWineGlassCrack } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareX } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareY } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquareZ } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquid } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSquirrel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStaff } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStandardDefinition } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarChristmas } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarSharp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarSharpHalf } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarSharpHalfAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarSharpHalfStroke } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarShooting } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarfighter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarfighterAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarfighterAltAdvanced } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarfighterTwinIonEngine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarfighterTwinIonEngineAdvanced } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStars } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarship } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStarshipFreighter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSteak } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSteeringWheel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStocking } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStomach } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStoreLock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStrawberry } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faStretcher } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSubtitles } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSubtitlesSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSubwayTunnel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSunAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSunBright } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSunCloud } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSunDust } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSunHaze } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSunglasses } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSunrise } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSunset } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSushi } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSushiRoll } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSwap } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSwapArrows } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSword } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSwordLaser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSwordLaserAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSwords } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSwordsLaser } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faSymbols } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTRex } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTableCellsColumnUnlock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTableCellsLock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTableCellsUnlock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTableLayout } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTablePicnic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTablePivot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTableRows } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTableTree } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTabletAndroidAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTabletRugged } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTabletScreen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTachometerAltFastest } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTachometerAltSlow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTachometerAltSlowest } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTachometerFastest } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTachometerSlow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTachometerSlowest } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTaco } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTally } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTally1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTally2 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTally3 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTally4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTally5 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTamale } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTankWater } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTaxiBus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTeddyBear } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTelescope } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTeletypeAnswer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTemperatureFrigid } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTemperatureHot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTemperatureList } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTemperatureSnow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTemperatureSun } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTennisBall } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTentDoublePeak } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faText } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTextSize } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTheta } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faThoughtBubble } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faThunderstormMoon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faThunderstormSun } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTick } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTicketAirline } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTicketPerforated } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTicketPerforatedPlane } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTicketPlane } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTickets } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTicketsAirline } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTicketsPerforated } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTicketsPerforatedPlane } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTicketsPlane } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTicketsSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTilde } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTimelineArrow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTimer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTimesHexagon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTimesOctagon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTimesToSlot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTire } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTireFlat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTirePressureWarning } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTireRugged } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToggleLargeOff } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToggleLargeOn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToiletPaperAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToiletPaperBlank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToiletPaperBlankUnder } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToiletPaperCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToiletPaperReverse } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToiletPaperReverseAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToiletPaperReverseSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToiletPaperUnder } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToiletPaperUnderSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToiletPaperXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTomato } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTombstone } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTombstoneAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTombstoneBlank } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faToothbrush } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTowerControl } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrafficCone } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrafficLightGo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrafficLightSlow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrafficLightStop } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrainSubwayTunnel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrainTrack } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrainTunnel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTransformerBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTransporter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTransporter1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTransporter2 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTransporter3 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTransporter4 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTransporter5 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTransporter6 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTransporter7 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTransporterEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashAltSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashArrowTurnLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashCanArrowTurnLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashCanCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashCanClock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashCanList } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashCanPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashCanSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashCanUndo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashCanXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashCheck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashClock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashList } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashUndo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashUndoAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrashXmark } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTreasureChest } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTreeAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTreeChristmas } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTreeDeciduous } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTreeDecorated } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTreeLarge } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTreePalm } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrees } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrianBalbot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTriangle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTriangleInstrument } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTriangleMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrianglePersonDigging } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTricycle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTricycleAdult } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrillium } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrophyAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrophyStar } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckClock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckContainer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckContainerEmpty } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckCouch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckFire } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckFlatbed } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckLadder } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckPlow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckRamp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckRampCouch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckTow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTruckUtensils } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTrumpet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTtyAnswer } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTugrikSign } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTurkey } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTurnDownLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTurnDownRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTurnLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTurnLeftDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTurnLeftUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTurnRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTurntable } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTurtle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTvMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTvRetro } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faTypewriter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUfo } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUfoBeam } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUmbrellaAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUmbrellaSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUnicorn } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUniformMartialArts } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUnion } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUpFromBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUpFromDottedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUpFromLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUpLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUpRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUpToBracket } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUpToDottedLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUpToLine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUsbDrive } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUsdCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUsdSquare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserAlien } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserBeardBolt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserBountyHunter } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserChart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserChef } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserConstruction } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserCowboy } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserCrown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserDoctorHair } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserDoctorHairLong } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserDoctorMessage } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserGroupCrown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserGroupSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserHair } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserHairBuns } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserHairLong } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserHairMullet } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserHardHat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserHeadset } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserHelmetSafety } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserHoodie } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserMagnifyingGlass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserMdChat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserMusic } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserNurseHair } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserNurseHairLong } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserPilot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserPilotTie } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserPolice } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserPoliceTie } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserRobot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserRobotXmarks } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserShakespeare } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserTieHair } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserTieHairLong } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserUnlock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserVisor } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserVneck } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserVneckHair } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUserVneckHairLong } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUsersClass } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUsersCrown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUsersMedical } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUtensilFork } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUtensilKnife } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUtensilsAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUtensilsSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUtilityPole } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faUtilityPoleDouble } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVacuum } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVacuumRobot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faValueAbsolute } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVectorCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVectorPolygon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVentDamper } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVhs } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVideoArrowDownLeft } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVideoArrowUpRight } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVideoCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVideoHandheld } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVideoPlus } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faViolin } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVolume } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVolumeMedium } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVolumeSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faVoteNay } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaffle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWagonCovered } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWalker } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWallBrick } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWand } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWarehouseAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWarehouseFull } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWasher } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWashingMachine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWatch } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWatchApple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWatchCalculator } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWatchFitness } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWatchSmart } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaterArrowDown } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaterArrowUp } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaterLower } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaterRise } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWatermelonSlice } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWave } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWavePulse } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaveSine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaveTriangle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaveform } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaveformCircle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaveformLines } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWaveformPath } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWavesSine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWebcam } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWebcamSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWebhook } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWhale } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWheat } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWheatAwnSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWheatSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWhiskeyGlassIce } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWhistle } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWifi1 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWifi2 } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWifiExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWifiFair } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWifiSlash } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWifiWeak } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWindCircleExclamation } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWindTurbine } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWindWarning } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWindow } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWindowAlt } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWindowFlip } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWindowFrame } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWindowFrameOpen } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWindsock } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWineGlassCrack } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWreath } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWreathLaurel } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faWrenchSimple } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faXmarkHexagon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faXmarkLarge } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faXmarkOctagon } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faXmarkToSlot } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faZzz } from "@fortawesome/free-solid-svg-icons/faSquare"; +export { definition as faActors, definition as faActorsBorderless, definition as faGb, definition as faLinear, definition as faProject, definition as faRegex, definition as faRivet, definition as faSelect, definition as faTs, definition as faVercel, definition as faWord } from "@fortawesome/free-solid-svg-icons/faSquare"; \ No newline at end of file diff --git a/frontend/packages/icons/src/package.json b/frontend/packages/icons/src/package.json new file mode 100644 index 0000000000..fbff5f658e --- /dev/null +++ b/frontend/packages/icons/src/package.json @@ -0,0 +1,10 @@ +{ + "name": "@rivet-gg/internal-icons", + "private": true, + "sideEffects": false, + "dependencies": { + "@awesome.me/kit-63db24046b": "^1.0.13", + "@fortawesome/pro-regular-svg-icons": "6.6.0", + "@fortawesome/pro-solid-svg-icons": "6.6.0" + } +} \ No newline at end of file diff --git a/frontend/apps/hub/postcss.config.js b/frontend/postcss.config.js similarity index 100% rename from frontend/apps/hub/postcss.config.js rename to frontend/postcss.config.js diff --git a/frontend/apps/studio/public/favicon.svg b/frontend/public/favicon.svg similarity index 100% rename from frontend/apps/studio/public/favicon.svg rename to frontend/public/favicon.svg diff --git a/frontend/public/logo.svg b/frontend/public/logo.svg new file mode 100644 index 0000000000..a7a146cc65 --- /dev/null +++ b/frontend/public/logo.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/frontend/src/app.tsx b/frontend/src/app.tsx new file mode 100644 index 0000000000..42b634ea31 --- /dev/null +++ b/frontend/src/app.tsx @@ -0,0 +1,61 @@ +import * as Sentry from "@sentry/react"; +import { QueryClientProvider } from "@tanstack/react-query"; +import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; +import { createRouter, RouterProvider } from "@tanstack/react-router"; +import { Suspense, useEffect } from "react"; +import { + ConfigProvider, + FullscreenLoading, + getConfig, + ThirdPartyProviders, + Toaster, + TooltipProvider, +} from "@/components"; +import { PageLayout } from "@/components/layout"; +import { queryClient } from "./queries/global"; +import { routeTree } from "./routeTree.gen"; +import { initializeShiftKeyTracking } from "./stores/shift-key-store"; + +declare module "@tanstack/react-router" { + interface Register { + router: typeof router; + } +} + +export const router = createRouter({ + basepath: import.meta.env.BASE_URL, + routeTree, + defaultStaleTime: Number.POSITIVE_INFINITY, + defaultPendingComponent: PageLayout.Root.Skeleton, + defaultPreloadStaleTime: 0, + defaultOnCatch: (error) => { + Sentry.captureException(error); + }, +}); + +function InnerApp() { + return ; +} + +export function App() { + useEffect(() => { + return initializeShiftKeyTracking(); + }, []); + return ( + + + + }> + + + + + + + + + + + + ); +} diff --git a/frontend/src/app/actor-builds-list.tsx b/frontend/src/app/actor-builds-list.tsx new file mode 100644 index 0000000000..190b79dfd8 --- /dev/null +++ b/frontend/src/app/actor-builds-list.tsx @@ -0,0 +1,79 @@ +import { + // @ts-expect-error + faActorsBorderless, + Icon, +} from "@rivet-gg/icons"; +import { useInfiniteQuery } from "@tanstack/react-query"; +import { Link, useNavigate } from "@tanstack/react-router"; +import { Fragment } from "react"; +import { Button, cn, Skeleton } from "@/components"; +import { ACTORS_PER_PAGE, useManager } from "@/components/actors"; +import { VisibilitySensor } from "@/components/visibility-sensor"; + +export function ActorBuildsList() { + const { data, isLoading, hasNextPage, fetchNextPage, isFetchingNextPage } = + useInfiniteQuery(useManager().buildsQueryOptions()); + + const navigate = useNavigate({ from: "/" }); + + return ( +
+
+ {data?.length === 0 ? ( +

+ No instances found. +

+ ) : null} + {data?.map((build) => ( + + ))} + {isFetchingNextPage || isLoading + ? Array(ACTORS_PER_PAGE) + .fill(null) + .map((_, i) => ( + + + + )) + : null} +
+ {hasNextPage ? : null} +
+ ); +} diff --git a/frontend/src/app/actors.tsx b/frontend/src/app/actors.tsx new file mode 100644 index 0000000000..101b974cf0 --- /dev/null +++ b/frontend/src/app/actors.tsx @@ -0,0 +1,64 @@ +import { useQuery } from "@tanstack/react-query"; +import { useNavigate, useSearch } from "@tanstack/react-router"; +import { + ActorFeature, + type ActorId, + ActorNotFound, + ActorsActorDetails, + ActorsActorEmptyDetails, + ActorsListPreview, + useManager, +} from "@/components/actors"; + +export function Actors({ actorId }: { actorId: string | undefined }) { + return ( + + {actorId ? ( + + ) : ( + + )} + + ); +} + +function Actor() { + const navigate = useNavigate(); + const { tab, actorId } = useSearch({ from: "/_layout" }); + + const { data, isError } = useQuery( + useManager().actorQueryOptions(actorId as ActorId), + ); + + if (!data || isError) { + return ( + + ); + } + + return ( + { + navigate({ + to: ".", + search: (old) => ({ ...old, tab }), + }); + }} + /> + ); +} diff --git a/frontend/src/app/credentials-context.tsx b/frontend/src/app/credentials-context.tsx new file mode 100644 index 0000000000..d40ea1dd47 --- /dev/null +++ b/frontend/src/app/credentials-context.tsx @@ -0,0 +1,19 @@ +import { createContext, useContext } from "react"; + +export type InspectorCredentials = { + url: string; + token: string; +}; + +export const InspectorCredentialsContext = createContext<{ + credentials: InspectorCredentials | null; + setCredentials: (creds: InspectorCredentials | null) => void; +}>({ credentials: null, setCredentials: () => {} }); + +export const useInspectorCredentials = () => { + const ctx = useContext(InspectorCredentialsContext); + return ctx; +}; + +export const InspectorCredentialsProvider = + InspectorCredentialsContext.Provider; diff --git a/frontend/src/app/dialogs/create-namespace-dialog.tsx b/frontend/src/app/dialogs/create-namespace-dialog.tsx new file mode 100644 index 0000000000..f0e890d2c9 --- /dev/null +++ b/frontend/src/app/dialogs/create-namespace-dialog.tsx @@ -0,0 +1,57 @@ +import { useMutation, useQueryClient } from "@tanstack/react-query"; +import { useNavigate } from "@tanstack/react-router"; +import * as CreateNamespaceForm from "@/app/forms/create-namespace-form"; +import { DialogFooter, DialogHeader, DialogTitle, Flex } from "@/components"; +import { convertStringToId } from "@/lib/utils"; +import { + managerClient, + namespacesQueryOptions, +} from "@/queries/manager-engine"; + +export default function CreateNamespacesDialogContent() { + const queryClient = useQueryClient(); + const navigate = useNavigate(); + + const { mutateAsync } = useMutation({ + mutationFn: async (data: { displayName: string; nameId: string }) => { + const response = await managerClient.namespaces.create({ + displayName: data.displayName, + name: data.nameId, + }); + + return response; + }, + onSuccess: async (data) => { + await queryClient.invalidateQueries(namespacesQueryOptions()); + navigate({ + to: "/ns/$namespace", + params: { namespace: data.namespace.name }, + }); + }, + }); + + return ( + { + await mutateAsync({ + displayName: values.name, + nameId: values.slug || convertStringToId(values.name), + }); + }} + defaultValues={{ name: "", slug: "" }} + > + + Create New Namespace + + + + + + + + Create + + + + ); +} diff --git a/frontend/src/app/forms/create-namespace-form.tsx b/frontend/src/app/forms/create-namespace-form.tsx new file mode 100644 index 0000000000..9304f117d6 --- /dev/null +++ b/frontend/src/app/forms/create-namespace-form.tsx @@ -0,0 +1,90 @@ +import { type UseFormReturn, useFormContext } from "react-hook-form"; +import z from "zod"; +import { + createSchemaForm, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, + Input, +} from "@/components"; +import { convertStringToId } from "@/lib/utils"; + +export const formSchema = z.object({ + name: z + .string() + .max(25) + .refine((value) => value.trim() !== "" && value.trim() === value, { + message: "Name cannot be empty or contain whitespaces", + }), + slug: z.string().max(25).optional(), +}); + +export type FormValues = z.infer; +export type SubmitHandler = ( + values: FormValues, + form: UseFormReturn, +) => Promise; + +const { Form, Submit, SetValue } = createSchemaForm(formSchema); +export { Form, Submit, SetValue }; + +export const Name = ({ className }: { className?: string }) => { + const { control } = useFormContext(); + return ( + ( + + Name + + + + + + )} + /> + ); +}; + +export const Slug = ({ className }: { className?: string }) => { + const { control, watch } = useFormContext(); + + const name = watch("name"); + + return ( + ( + + Slug + + { + const value = convertStringToId( + event.target.value, + ); + field.onChange({ target: { value } }); + }} + /> + + + + )} + /> + ); +}; diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx new file mode 100644 index 0000000000..bb9df524ae --- /dev/null +++ b/frontend/src/app/layout.tsx @@ -0,0 +1,407 @@ +import { + faArrowUpRight, + faCheck, + faLink, + faServer, + faSpinnerThird, + faTriangleExclamation, + Icon, +} from "@rivet-gg/icons"; +import { useQuery } from "@tanstack/react-query"; +import { Link, useMatchRoute, useNavigate } from "@tanstack/react-router"; +import { + type ComponentProps, + createContext, + type PropsWithChildren, + type ReactNode, + type RefObject, + Suspense, + useContext, + useLayoutEffect, + useRef, + useState, +} from "react"; +import type { ImperativePanelGroupHandle } from "react-resizable-panels"; +import { + Button, + cn, + DocsSheet, + type ImperativePanelHandle, + ResizableHandle, + ResizablePanel, + ResizablePanelGroup, + ScrollArea, + Skeleton, +} from "@/components"; +import { useManager } from "@/components/actors"; +import type { HeaderLinkProps } from "@/components/header/header-link"; +import { ensureTrailingSlash } from "@/lib/utils"; +import type { NamespaceNameId } from "@/queries/manager-engine"; +import { ActorBuildsList } from "./actor-builds-list"; +import { useInspectorCredentials } from "./credentials-context"; +import { NamespaceSelect } from "./namespace-select"; + +interface RootProps { + children: ReactNode; +} + +const Root = ({ children }: RootProps) => { + return
{children}
; +}; + +const Main = ({ + children, + ref, +}: RootProps & { ref?: RefObject }) => { + return ( + +
+ {children} +
+
+ ); +}; + +const SidebarDimensionsContext = createContext(0); +const SIDEBAR_MIN_WIDTH = 195; /* in px */ + +const VisibleInFull = ({ children }: PropsWithChildren) => { + const groupRef = useRef(null); + + const [sidebarMinWidth, setSidebarMinWidth] = useState(0); + + useLayoutEffect(() => { + const panelGroup = document.querySelector( + '[data-panel-group-id="root"]', + ); + const resizeHandles = panelGroup?.querySelectorAll( + "[data-panel-resize-handle-id]", + ); + + if (!panelGroup || !resizeHandles || resizeHandles?.length === 0) { + return; + } + + const observer = new ResizeObserver(() => { + let width = panelGroup.offsetWidth; + + resizeHandles.forEach((resizeHandle) => { + width -= resizeHandle.offsetWidth; + }); + + setSidebarMinWidth((SIDEBAR_MIN_WIDTH / width) * 100); + }); + observer.observe(panelGroup); + resizeHandles.forEach((resizeHandle) => { + observer.observe(resizeHandle); + }); + + return () => { + observer.unobserve(panelGroup); + resizeHandles.forEach((resizeHandle) => { + observer.unobserve(resizeHandle); + }); + observer.disconnect(); + }; + }, []); + + return ( + + + {children} + + + ); +}; + +const Sidebar = ({ + ref, + ...props +}: { + ref?: RefObject; +} & ComponentProps) => { + const sidebarMinWidth = useContext(SidebarDimensionsContext); + return ( + <> + +
+ + Rivet.gg + +
+ {__APP_TYPE__ === "inspector" ? ( + + ) : null} + {__APP_TYPE__ === "engine" ? : null} + + + +
+
+
+ + + + + + +
+
+
+
+ + + ); +}; + +const Header = () => { + return null; +}; + +const Footer = () => { + return null; +}; + +export { Root, Main, Header, Footer, VisibleInFull, Sidebar }; + +const Breadcrumbs = () => { + const matchRoute = useMatchRoute(); + const nsMatch = matchRoute({ + to: "/ns/$namespace", + fuzzy: true, + }); + + if (nsMatch === false) { + return null; + } + + return ( + + +
+ } + > + + + ); +}; + +const NamespaceBreadcrumbs = ({ + namespaceNameId, +}: { + namespaceNameId: NamespaceNameId; +}) => { + const navigate = useNavigate(); + + return ( +
+ { + navigate({ + to: "/ns/$namespace", + params: { + namespace: value, + }, + }); + }} + onCreateClick={() => { + navigate({ + to: ".", + search: (old) => ({ + ...old, + modal: "create-ns", + }), + }); + }} + /> +
+ ); +}; + +const Subnav = () => { + const matchRoute = useMatchRoute(); + const nsMatch = matchRoute( + __APP_TYPE__ === "engine" + ? { + to: "/ns/$namespace", + fuzzy: true, + } + : { to: "/", fuzzy: true }, + ); + + if (nsMatch === false) { + return null; + } + + return ( +
+ {__APP_TYPE__ === "engine" ? ( + + Runners + + ) : null} +
+ + Instances + + +
+
+ ); +}; + +function HeaderLink({ icon, children, className, ...props }: HeaderLinkProps) { + return ( + + ); +} + +function ConnectionStatus() { + const { endpoint, ...queries } = useManager(); + const { setCredentials } = useInspectorCredentials(); + const { isLoading, isError, isSuccess } = useQuery( + queries.managerStatusQueryOptions(), + ); + + if (isLoading) { + return ( +
+
+

Connecting

+

{endpoint}

+
+ +
+ ); + } + + // if (isError) { + return ( +
+
+
+

Disconnected

+

{endpoint}

+
+
+ + +
+ ); + // } + + if (isSuccess) { + return ( +
+
+

Connected

+

{endpoint}

+
+
+ ); + } +} diff --git a/frontend/src/app/namespace-select.tsx b/frontend/src/app/namespace-select.tsx new file mode 100644 index 0000000000..843a4e798a --- /dev/null +++ b/frontend/src/app/namespace-select.tsx @@ -0,0 +1,92 @@ +import { SelectGroup } from "@radix-ui/react-select"; +import { faCirclePlus, faSpinnerThird, Icon } from "@rivet-gg/icons"; +import { useInfiniteQuery } from "@tanstack/react-query"; +import { type ComponentProps, useCallback, useEffect, useRef } from "react"; +import { + Flex, + Select, + SelectContent, + SelectItem, + SelectLabel, + SelectSeparator, + SelectTrigger, + SelectValue, +} from "@/components"; +import { VisibilitySensor } from "@/components/visibility-sensor"; +import { namespacesQueryOptions } from "@/queries/manager-engine"; + +interface NamespaceSelectProps extends ComponentProps { + showCreate?: boolean; + onCreateClick?: () => void; + variant?: ComponentProps["variant"]; + className?: string; +} + +export function NamespaceSelect({ + showCreate, + onCreateClick, + onValueChange, + variant, + className, + ...props +}: NamespaceSelectProps) { + const { data, hasNextPage, fetchNextPage, isFetchingNextPage } = + useInfiniteQuery(namespacesQueryOptions()); + + const handleValueChange = useCallback( + (value: string) => { + if (value === "%%create%%") { + onCreateClick?.(); + return; + } + onValueChange?.(value); + }, + [onCreateClick, onValueChange], + ); + + return ( + + ); +} diff --git a/frontend/src/app/use-dialog.tsx b/frontend/src/app/use-dialog.tsx new file mode 100644 index 0000000000..1bafdb0e83 --- /dev/null +++ b/frontend/src/app/use-dialog.tsx @@ -0,0 +1,9 @@ +import { createDialogHook, useDialog } from "@/components/actors"; + +const d = useDialog as typeof useDialog & + Record>; +d.CreateNamespace = createDialogHook( + import("@/app/dialogs/create-namespace-dialog"), +); + +export { d as useDialog }; diff --git a/frontend/src/components/action-card.tsx b/frontend/src/components/action-card.tsx new file mode 100644 index 0000000000..489078baaa --- /dev/null +++ b/frontend/src/components/action-card.tsx @@ -0,0 +1,44 @@ +"use client"; +import type { ReactNode } from "react"; +import { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from "./ui/card"; + +export interface ActionCardProps { + title: string; + description?: ReactNode; + children?: ReactNode; + action?: ReactNode; + footer?: ReactNode; + className?: string; +} + +export const ActionCard = ({ + title, + action, + footer, + description, + className, + children, +}: ActionCardProps) => { + return ( + + +
+ {title} + {action} +
+ {description ? ( + {description} + ) : null} +
+ {children ? {children} : null} + {footer ? {footer} : null} +
+ ); +}; diff --git a/frontend/src/components/actors/actor-build.tsx b/frontend/src/components/actors/actor-build.tsx new file mode 100644 index 0000000000..8aec80481b --- /dev/null +++ b/frontend/src/components/actors/actor-build.tsx @@ -0,0 +1,64 @@ +import { useQuery } from "@tanstack/react-query"; +import { formatISO } from "date-fns"; +import { Dd, DiscreteCopyButton, Dl, Dt, Flex } from "@/components"; +import { useManager } from "./manager-context"; +import type { ActorId } from "./queries"; + +interface ActorBuildProps { + actorId: ActorId; +} + +export function ActorBuild({ actorId }: ActorBuildProps) { + const { data } = useQuery(useManager().actorBuildQueryOptions(actorId)); + + if (!data) { + return null; + } + + return ( +
+
+

Build

+
+ +
+
ID
+
+ + {data.id} + +
+
Created
+
+ + {formatISO(data.createdAt)} + +
+
Tags
+
+ + + +
+
+
+
+ ); +} diff --git a/frontend/src/components/actors/actor-clear-events-log-button.tsx b/frontend/src/components/actors/actor-clear-events-log-button.tsx new file mode 100644 index 0000000000..3c35506e2a --- /dev/null +++ b/frontend/src/components/actors/actor-clear-events-log-button.tsx @@ -0,0 +1,26 @@ +import { faBroomWide, Icon } from "@rivet-gg/icons"; +import { Button } from "../ui/button"; +import { WithTooltip } from "../ui/tooltip"; +import { type ActorId, useActorClearEventsMutation } from "./queries"; + +export function ActorClearEventsLogButton({ actorId }: { actorId: ActorId }) { + const { mutate, isPending } = useActorClearEventsMutation(actorId); + + return ( + { + mutate(); + }} + > + + + } + /> + ); +} diff --git a/frontend/src/components/actors/actor-config-tab.tsx b/frontend/src/components/actors/actor-config-tab.tsx new file mode 100644 index 0000000000..19b9b5841c --- /dev/null +++ b/frontend/src/components/actors/actor-config-tab.tsx @@ -0,0 +1,31 @@ +import { faBooks, Icon } from "@rivet-gg/icons"; +import { Button, DocsSheet, ScrollArea } from "@/components"; +import { ActorGeneral } from "./actor-general"; +import { ActorNetwork } from "./actor-network"; +import { ActorRuntime } from "./actor-runtime"; +import type { ActorId } from "./queries"; + +interface ActorConfigTabProps { + actorId: ActorId; +} + +export function ActorConfigTab(props: ActorConfigTabProps) { + return ( + +
+ + + +
+ + + +
+ ); +} diff --git a/frontend/src/components/actors/actor-connections-tab.tsx b/frontend/src/components/actors/actor-connections-tab.tsx new file mode 100644 index 0000000000..3f3ea5ee5b --- /dev/null +++ b/frontend/src/components/actors/actor-connections-tab.tsx @@ -0,0 +1,66 @@ +import { useQuery } from "@tanstack/react-query"; +import { LiveBadge, ScrollArea } from "@/components"; +import { useActor } from "./actor-queries-context"; +import { ActorObjectInspector } from "./console/actor-inspector"; +import { useManager } from "./manager-context"; +import { type ActorId, useActorConnectionsStream } from "./queries"; + +interface ActorConnectionsTabProps { + actorId: ActorId; +} + +export function ActorConnectionsTab({ actorId }: ActorConnectionsTabProps) { + const { data: destroyedAt } = useQuery( + useManager().actorDestroyedAtQueryOptions(actorId), + ); + + const actorQueries = useActor(); + const { + data: { connections } = {}, + isError, + isLoading, + } = useQuery(actorQueries.actorConnectionsQueryOptions(actorId)); + + // useActorConnectionsStream(actorId); + + if (destroyedAt) { + return ( +
+ Connections Preview is unavailable for inactive Actors. +
+ ); + } + + if (isError) { + return ( +
+ Connections Preview is currently unavailable. +
+ See console/logs for more details. +
+ ); + } + + if (isLoading) { + return ( +
+ Loading connections... +
+ ); + } + + return ( + +
+ +
+
+ +
+
+ ); +} diff --git a/frontend/src/components/actors/actor-context.tsx b/frontend/src/components/actors/actor-context.tsx new file mode 100644 index 0000000000..be3b960f60 --- /dev/null +++ b/frontend/src/components/actors/actor-context.tsx @@ -0,0 +1,4 @@ +export { + createActorInspectorClient, + createManagerInspectorClient, +} from "@rivetkit/core/inspector"; diff --git a/frontend/src/components/actors/actor-cpu-stats.tsx b/frontend/src/components/actors/actor-cpu-stats.tsx new file mode 100644 index 0000000000..2cf694f339 --- /dev/null +++ b/frontend/src/components/actors/actor-cpu-stats.tsx @@ -0,0 +1,149 @@ +import { format } from "date-fns"; +import { useId } from "react"; +import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from "recharts"; +import { timing } from "../lib/timing"; +import { + type ChartConfig, + ChartContainer, + ChartTooltip, + ChartTooltipContent, +} from "../ui/chart"; + +interface ActorCpuStatsProps { + interval?: number; + cpu: number[]; + metricsAt: number; + syncId?: string; + isRunning?: boolean; +} + +const chartConfig = { + value: { + color: "hsl(var(--chart-1))", + label: "CPU Usage", + }, +} satisfies ChartConfig; + +export function ActorCpuStats({ + interval = 15, + cpu, + metricsAt, + syncId, + isRunning = true, +}: ActorCpuStatsProps) { + // Filter out trailing zeros in the last 15 seconds only if actor is still running + let filteredCpu = [...cpu]; + if (isRunning) { + const secondsToCheck = 15; + const pointsToCheck = Math.ceil(secondsToCheck / interval); + + // Find the last non-zero value and cut off any zeros after it + for ( + let i = filteredCpu.length - 1; + i >= Math.max(0, filteredCpu.length - pointsToCheck); + i-- + ) { + if (filteredCpu[i] === 0) { + filteredCpu = filteredCpu.slice(0, i); + } else { + break; + } + } + } + + const data = filteredCpu.map((value, i) => { + let cpuPercent = 0; + + // Calculate CPU percentage using delta time between ticks + if (i > 0) { + const currentCpuTime = value; + const previousCpuTime = filteredCpu[i - 1]; + const deltaTime = interval; // seconds between measurements + + // CPU percentage = (cpu_time_delta / time_delta) * 100 + // This gives us the percentage of CPU time used in the interval + if (currentCpuTime >= previousCpuTime) { + cpuPercent = Math.min( + ((currentCpuTime - previousCpuTime) / deltaTime) * 100, + 100, + ); + } + } + + return { + x: `${(filteredCpu.length - i) * -interval}`, + value: cpuPercent / 100, // Convert to 0-1 range for chart + config: { + label: new Date( + metricsAt - + (filteredCpu.length - i) * timing.seconds(interval), + ), + }, + }; + }); + + const id = useId(); + + const fillId = `fill-${id}`; + return ( + + + + + `${value * 100}%`} + /> + { + return format(label, "HH:mm:ss"); + }} + valueFormatter={(value) => { + if (typeof value !== "number") { + return "n/a"; + } + return `${(value * 100).toFixed(2)}%`; + }} + /> + } + /> + + + + + + + + + + ); +} diff --git a/frontend/src/components/actors/actor-database.tsx b/frontend/src/components/actors/actor-database.tsx new file mode 100644 index 0000000000..8fbe6079a8 --- /dev/null +++ b/frontend/src/components/actors/actor-database.tsx @@ -0,0 +1,157 @@ +import { faRefresh, faTable, faTableCells, Icon } from "@rivet-gg/icons"; +import { useQuery } from "@tanstack/react-query"; +import { useState } from "react"; +import { ShimmerLine } from "../shimmer-line"; +import { Button } from "../ui/button"; +import { Flex } from "../ui/flex"; +import { ScrollArea } from "../ui/scroll-area"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "../ui/select"; +import { WithTooltip } from "../ui/tooltip"; +import { useActor } from "./actor-queries-context"; +import { DatabaseTable } from "./database/database-table"; +import type { ActorId } from "./queries"; + +interface ActorDatabaseProps { + actorId: ActorId; +} + +export function ActorDatabase({ actorId }: ActorDatabaseProps) { + const actorQueries = useActor(); + const { data, refetch } = useQuery( + actorQueries.actorDatabaseQueryOptions(actorId), + ); + const [table, setTable] = useState( + () => data?.db[0]?.table.name, + ); + + const selectedTable = table || data?.db[0]?.table.name; + + const { + data: rows, + refetch: refetchData, + isLoading, + } = useQuery( + actorQueries.actorDatabaseRowsQueryOptions(actorId, selectedTable!, { + enabled: !!selectedTable, + }), + ); + + const currentTable = data?.db.find((db) => db.table.name === selectedTable); + + return ( + <> +
+
+ +
+
+ + + {currentTable ? ( + <> + {currentTable.table.schema}. + {currentTable.table.name} + + ({currentTable.columns.length} columns,{" "} + {currentTable.records} rows) + + + ) : ( + + No table selected + + )} + +
+
+ { + refetch(); + refetchData(); + }} + > + + + } + /> +
+
+
+ {isLoading ? : null} + + {currentTable ? ( + + ) : null} + +
+ + ); +} + +function TableSelect({ + actorId, + value, + onSelect, +}: { + actorId: ActorId; + onSelect: (table: string) => void; + value: string | undefined; +}) { + const actorQueries = useActor(); + const { data: tables } = useQuery( + actorQueries.actorDatabaseTablesQueryOptions(actorId), + ); + + return ( + + ); +} diff --git a/frontend/src/components/actors/actor-db-tab.tsx b/frontend/src/components/actors/actor-db-tab.tsx new file mode 100644 index 0000000000..746473145d --- /dev/null +++ b/frontend/src/components/actors/actor-db-tab.tsx @@ -0,0 +1,59 @@ +import { useQuery } from "@tanstack/react-query"; +import { ActorDatabase } from "./actor-database"; +import { useActor } from "./actor-queries-context"; +import { Info } from "./actor-state-tab"; +import { useManager } from "./manager-context"; +import type { ActorId } from "./queries"; + +interface ActorDatabaseTabProps { + actorId: ActorId; +} + +export function ActorDatabaseTab({ actorId }: ActorDatabaseTabProps) { + const { data: destroyedAt } = useQuery( + useManager().actorDestroyedAtQueryOptions(actorId), + ); + + const actorQueries = useActor(); + const { + data: isEnabled, + isLoading, + isError, + } = useQuery(actorQueries.actorDatabaseEnabledQueryOptions(actorId)); + + if (destroyedAt) { + return Database Studio is unavailable for inactive Actors.; + } + + if (isError) { + return ( + + Database Studio is currently unavailable. +
+ See console/logs for more details. +
+ ); + } + + if (isLoading) { + return Loading...; + } + + if (!isEnabled) { + return ( + +

+ Database Studio is not enabled for this Actor.
You + can enable it by providing a valid database connection + provider. +

+
+ ); + } + + return ( +
+ +
+ ); +} diff --git a/frontend/src/components/actors/actor-details-settings-button.tsx b/frontend/src/components/actors/actor-details-settings-button.tsx new file mode 100644 index 0000000000..cb5de549a0 --- /dev/null +++ b/frontend/src/components/actors/actor-details-settings-button.tsx @@ -0,0 +1,65 @@ +import { faCog, Icon } from "@rivet-gg/icons"; +import { + Button, + cn, + DropdownMenu, + DropdownMenuCheckboxItem, + DropdownMenuContent, + DropdownMenuTrigger, + WithTooltip, +} from "@/components"; +import { useActorDetailsSettings } from "./actor-details-settings"; + +interface ActorDetailsSettingsButtonProps { + className?: string; +} + +export function ActorDetailsSettingsButton({ + className, +}: ActorDetailsSettingsButtonProps) { + const [settings, setSettings] = useActorDetailsSettings(); + + return ( + + + + + } + content="Settings" + /> + + { + setSettings((old) => ({ + ...old, + showTimestamps: value, + })); + }} + > + Show timestamps + + { + setSettings((old) => ({ + ...old, + autoFollowLogs: value, + })); + }} + > + Auto follow logs when scrolled to bottom + + + + ); +} diff --git a/frontend/src/components/actors/actor-details-settings.tsx b/frontend/src/components/actors/actor-details-settings.tsx new file mode 100644 index 0000000000..49677005ca --- /dev/null +++ b/frontend/src/components/actors/actor-details-settings.tsx @@ -0,0 +1,41 @@ +import { + createContext, + type Dispatch, + type ReactNode, + type SetStateAction, + useContext, +} from "react"; +import { useLocalStorage } from "usehooks-ts"; + +export interface Settings { + showTimestamps: boolean; + autoFollowLogs: boolean; +} + +export const ActorDetailsSettingsContext = createContext< + [Settings, Dispatch>, unknown] +>([{ showTimestamps: false, autoFollowLogs: true }, () => {}, {}]); + +export const useActorDetailsSettings = () => { + const value = useContext(ActorDetailsSettingsContext); + return value; +}; + +interface ActorDetailsSettingsProviderProps { + children: ReactNode; +} + +export const ActorDetailsSettingsProvider = ({ + children, +}: ActorDetailsSettingsProviderProps) => { + const localStorage = useLocalStorage("actor-details-settings", { + showTimestamps: false, + autoFollowLogs: true, + }); + + return ( + + {children} + + ); +}; diff --git a/frontend/src/components/actors/actor-download-logs-button.tsx b/frontend/src/components/actors/actor-download-logs-button.tsx new file mode 100644 index 0000000000..ffebcd83d8 --- /dev/null +++ b/frontend/src/components/actors/actor-download-logs-button.tsx @@ -0,0 +1,126 @@ +import { faSave, Icon } from "@rivet-gg/icons"; +import saveAs from "file-saver"; +import { type Atom, atom, useAtom } from "jotai"; +import { selectAtom } from "jotai/utils"; +import { Button, WithTooltip } from "@/components"; +import type { ActorAtom, LogsAtom } from "./actor-context"; +import { + type Settings, + useActorDetailsSettings, +} from "./actor-details-settings"; +import { filterLogs, type LogsTypeFilter } from "./actor-logs"; +import type { ActorId } from "./queries"; + +// const downloadLogsAtom = atom( +// null, +// async ( +// get, +// _set, +// { +// actorId, +// typeFilter, +// filter, +// }: { +// actorId: string; +// typeFilter?: LogsTypeFilter; +// filter?: string; +// }, +// ) => { +// const environment = get(actorEnvironmentAtom); +// const exportHandler = get(exportLogsHandlerAtom); + +// if (!environment || !exportHandler) { +// throw new Error("Environment or export handler not available"); +// } + +// // Build query JSON for the API +// // Based on the GET logs endpoint usage, we need to build a query +// const query: any = { +// actorIds: [actorId], +// }; + +// // Add stream filter based on typeFilter +// if (typeFilter === "output") { +// query.stream = 0; // stdout +// } else if (typeFilter === "errors") { +// query.stream = 1; // stderr +// } + +// // Add text search if filter is provided +// if (filter) { +// query.searchText = filter; +// } + +// const result = await exportHandler({ +// projectNameId: environment.projectNameId, +// environmentNameId: environment.environmentNameId, +// queryJson: JSON.stringify(query), +// }); + +// // Open the presigned URL in a new tab to download +// window.open(result.url, "_blank"); +// }, +// ); + +interface ActorDownloadLogsButtonProps { + actorId: ActorId; + typeFilter?: LogsTypeFilter; + filter?: string; + onExportLogs?: ( + actorId: string, + typeFilter?: string, + filter?: string, + ) => Promise; + isExporting?: boolean; +} + +export function ActorDownloadLogsButton({ + actorId, + typeFilter, + filter, + onExportLogs, + isExporting = false, +}: ActorDownloadLogsButtonProps) { + // const [isDownloading, setIsDownloading] = useState(false); + // const [, downloadLogs] = useAtom(downloadLogsAtom); + // const actorData = useAtomValue(actor); + + // const handleDownload = async () => { + // try { + // setIsDownloading(true); + // await downloadLogs({ + // actorId: actorData.id, + // typeFilter, + // filter, + // }); + // } catch (error) { + // console.error("Failed to download logs:", error); + // } finally { + // setIsDownloading(false); + // } + // }; + // const [settings] = useActorDetailsSettings(); + + // const [, downloadLogs] = useAtom(downloadLogsAtom); + + return ( + + + + } + /> + ); +} diff --git a/frontend/src/components/actors/actor-editable-state.tsx b/frontend/src/components/actors/actor-editable-state.tsx new file mode 100644 index 0000000000..4a1e04bb36 --- /dev/null +++ b/frontend/src/components/actors/actor-editable-state.tsx @@ -0,0 +1,133 @@ +import { faRotateLeft, faSave, Icon } from "@rivet-gg/icons"; +import { AnimatePresence, motion } from "framer-motion"; +import { useMemo, useRef, useState } from "react"; +import { + Badge, + Button, + LiveBadge, + PauseBadge, + WithTooltip, +} from "@/components"; +import { + type CodeMirrorRef, + EditorView, + JsonCode, +} from "@/components/code-mirror"; +import { ActorStateChangeIndicator } from "./actor-state-change-indicator"; +import { + type ActorId, + useActorStatePatchMutation, + useActorStateStream, +} from "./queries"; + +const isValidJson = (json: string | null): json is string => { + if (!json) return false; + try { + JSON.parse(json); + return true; + } catch { + return false; + } +}; + +interface ActorEditableStateProps { + actorId: ActorId; + state: unknown; +} + +export function ActorEditableState({ + state, + actorId, +}: ActorEditableStateProps) { + const [isEditing, setIsEditing] = useState(false); + const [value, setValue] = useState(null); + + const ref = useRef(null); + + const formatted = useMemo(() => { + return JSON.stringify(state, null, 2); + }, [state]); + + const isValid = isValidJson(value) ? JSON.parse(value) : false; + + const { mutate, isPending } = useActorStatePatchMutation(actorId); + + // useActorStateStream(actorId); + + return ( + <> +
+
+ {isEditing ? : } + + +
+
+ + {isEditing ? ( + + + Modified + + + } + content="State has been modified and not saved." + /> + ) : null} + + { + mutate(JSON.parse(value || "")); + setIsEditing(false); + setValue(null); + }} + > + + + } + /> + { + setValue(null); + setIsEditing(false); + }} + > + + + } + /> +
+
+
+ { + setValue(value); + setIsEditing(true); + }} + /> +
+ + ); +} diff --git a/frontend/src/components/actors/actor-events-list.tsx b/frontend/src/components/actors/actor-events-list.tsx new file mode 100644 index 0000000000..2ac30d5b13 --- /dev/null +++ b/frontend/src/components/actors/actor-events-list.tsx @@ -0,0 +1,235 @@ +import { + faHammer, + faLink, + faMegaphone, + faTowerBroadcast, + faUnlink, + Icon, +} from "@rivet-gg/icons"; +import type { RecordedRealtimeEvent } from "@rivetkit/core/inspector"; +import { useQuery } from "@tanstack/react-query"; +import { format } from "date-fns"; +import { type PropsWithChildren, useEffect, useRef } from "react"; +import { Badge } from "../ui/badge"; +import { useActor } from "./actor-queries-context"; +import { ActorObjectInspector } from "./console/actor-inspector"; +import type { ActorId } from "./queries"; + +interface ActorEventsListProps { + actorId: ActorId; + search: string; + filter: string[]; +} + +export function ActorEventsList({ + actorId, + search, + filter, +}: ActorEventsListProps) { + const actorQueries = useActor(); + const { data, isLoading, isError } = useQuery( + actorQueries.actorEventsQueryOptions(actorId), + ); + + if (isLoading) { + return Loading events...; + } + + if (isError) { + return ( + + Realtime Events Preview is currently unavailable. +
+ See console/logs for more details. +
+ ); + } + + const filteredEvents = data?.events.filter?.((event) => { + const constraints = []; + + if ("name" in event) { + constraints.push( + event.name.toLowerCase().includes(search.toLowerCase()), + ); + } + if ("eventName" in event) { + constraints.push( + event.eventName.toLowerCase().includes(search.toLowerCase()), + ); + } + if (filter.length > 0) { + const type = event.type.includes("subscribe") + ? "subscription" + : event.type; + constraints.push(filter.includes(type)); + } + return constraints.every(Boolean); + }); + + if (filteredEvents?.length === 0) { + return No events found.; + } + + return filteredEvents?.map((event) => { + return ; + }); +} + +function Event(props: RecordedRealtimeEvent) { + const ref = useRef(null); + + useEffect(() => { + if (ref.current && props.timestamp > Date.now() - 1000) { + ref.current.animate( + [ + { backgroundColor: "transparent" }, + { backgroundColor: "hsl(var(--primary) / 15%)" }, + { backgroundColor: "transparent" }, + ], + { + duration: 1000, + fill: "forwards", + easing: "ease-in-out", + }, + ); + } + }, []); + + if (props.type === "action") { + return ( + +
+ {props.timestamp + ? format( + props.timestamp, + "LLL dd HH:mm:ss", + ).toUpperCase() + : null} +
+
+ {props.connId.split("-")[0]} +
+
+ + + Action + +
+
{props.name}
+
+ +
+
+ ); + } + if (props.type === "subscribe" || props.type === "unsubscribe") { + return ( + +
+ {props.timestamp + ? format( + props.timestamp, + "LLL dd HH:mm:ss", + ).toUpperCase() + : null} +
+
+ {props.connId.split("-")[0]} +
+
+ + + {props.type === "subscribe" + ? "Subscribe" + : "Unsubscribe"} + +
+
{props.eventName}
+
+ + ); + } + if (props.type === "broadcast") { + return ( + +
+ {props.timestamp + ? format( + props.timestamp, + "LLL dd HH:mm:ss", + ).toUpperCase() + : null} +
+
+
+ + + Broadcast + +
+
{props.eventName}
+
+ +
+ + ); + } + if (props.type === "event") { + return ( + +
+ {props.timestamp + ? format( + props.timestamp, + "LLL dd HH:mm:ss", + ).toUpperCase() + : null} +
+
+ {props.connId.split("-")[0]} +
+
+ + + Send + +
+
{props.eventName}
+
+ +
+
+ ); + } +} + +function EventContainer({ + ref, + children, +}: { + ref: React.RefObject; + children: React.ReactNode; +}) { + return ( +
+ {children} +
+ ); +} + +function Info({ children }: PropsWithChildren) { + return ( +
+ {children} +
+ ); +} diff --git a/frontend/src/components/actors/actor-events-tab.tsx b/frontend/src/components/actors/actor-events-tab.tsx new file mode 100644 index 0000000000..f42d08c979 --- /dev/null +++ b/frontend/src/components/actors/actor-events-tab.tsx @@ -0,0 +1,46 @@ +import { useQuery } from "@tanstack/react-query"; +import { ActorEvents } from "./actor-events"; +import { useActor } from "./actor-queries-context"; +import { Info } from "./actor-state-tab"; +import { useManager } from "./manager-context"; +import type { ActorId } from "./queries"; + +export type EventsTypeFilter = "action" | "subscription" | "broadcast" | "send"; + +interface ActorEventsTabProps { + actorId: ActorId; +} + +export function ActorEventsTab({ actorId }: ActorEventsTabProps) { + const { data: destroyedAt } = useQuery( + useManager().actorDestroyedAtQueryOptions(actorId), + ); + + const { isError, isLoading } = useQuery( + useActor().actorEventsQueryOptions(actorId), + ); + + if (destroyedAt) { + return ( +
+ State Preview is unavailable for inactive Actors. +
+ ); + } + + if (isError) { + return ( + + Database Studio is currently unavailable. +
+ See console/logs for more details. +
+ ); + } + + if (isLoading) { + return Loading...; + } + + return ; +} diff --git a/frontend/src/components/actors/actor-events.tsx b/frontend/src/components/actors/actor-events.tsx new file mode 100644 index 0000000000..4825f76f66 --- /dev/null +++ b/frontend/src/components/actors/actor-events.tsx @@ -0,0 +1,214 @@ +import { faPause, faPlay, Icon } from "@rivet-gg/icons"; +import { useQuery } from "@tanstack/react-query"; +import { + startTransition, + useCallback, + useEffect, + useRef, + useState, +} from "react"; +import { useResizeObserver } from "usehooks-ts"; +import { + Button, + LiveBadge, + LogsView, + PauseBadge, + ScrollArea, + ToggleGroup, + ToggleGroupItem, + WithTooltip, +} from "@/components"; +import { ActorClearEventsLogButton } from "./actor-clear-events-log-button"; +import { useActorDetailsSettings } from "./actor-details-settings"; +import { ActorDetailsSettingsButton } from "./actor-details-settings-button"; +import { ActorEventsList } from "./actor-events-list"; +import { useActor } from "./actor-queries-context"; +import { type ActorId, useActorEventsStream } from "./queries"; + +export type EventsTypeFilter = "action" | "subscription" | "broadcast" | "send"; + +interface ActorEventsProps { + actorId: ActorId; +} + +export function ActorEvents({ actorId }: ActorEventsProps) { + const [search, setSearch] = useState(""); + const [logsFilter, setLogsFilter] = useState([ + "action", + "subscription", + "broadcast", + "send", + ]); + + const [isLive, setIsLive] = useState(true); + const ref = useRef(null); + // useActorEventsStream(actorId, { enabled: isLive }); + const [settings] = useActorDetailsSettings(); + + const actorQueries = useActor(); + const { data } = useQuery(actorQueries.actorEventsQueryOptions(actorId)); + const { onScroll } = useScrollToBottom(ref, [data]); + + return ( +
+
+
+
+ + startTransition(() => setSearch(e.target.value)) + } + /> +
+ { + setLogsFilter(value as EventsTypeFilter[]); + }} + className="gap-0 text-xs p-2 border-r" + > + + Action + + + Subscription + + + Broadcast + + + Send + + +
+ + + setIsLive((prev) => !prev)} + > + + + } + /> +
+ {isLive ? : } +
+
+
+
+
+ +
+
+
+ Timestamp +
+
Connection
+
Event
+
Name
+
Data
+
+ + +
+
+
+
+ ); +} + +ActorEvents.Skeleton = () => { + return ( +
+ +
+ ); +}; + +function useScrollToBottom( + ref: React.RefObject, + deps: unknown[], +) { + const [settings] = useActorDetailsSettings(); + const follow = useRef(true); + const shouldFollow = () => settings.autoFollowLogs && follow.current; + useResizeObserver({ + ref, + onResize: () => { + if (shouldFollow()) { + // https://github.com/TanStack/virtual/issues/537 + requestAnimationFrame(() => { + ref.current?.scrollTo({ + top: ref.current.scrollHeight, + behavior: "smooth", + }); + }); + } + }, + }); + + const onScroll = useCallback((e: React.UIEvent) => { + follow.current = + e.currentTarget.scrollHeight - e.currentTarget.scrollTop <= + e.currentTarget.clientHeight; + }, []); + + useEffect(() => { + if (!shouldFollow()) { + return () => {}; + } + // https://github.com/TanStack/virtual/issues/537 + const rafId = requestAnimationFrame(() => { + ref.current?.scrollTo({ + top: ref.current.scrollHeight, + behavior: "smooth", + }); + }); + + return () => { + cancelAnimationFrame(rafId); + }; + }, deps); + + return { onScroll }; +} diff --git a/frontend/src/components/actors/actor-filters-context.tsx b/frontend/src/components/actors/actor-filters-context.tsx new file mode 100644 index 0000000000..22d0c46507 --- /dev/null +++ b/frontend/src/components/actors/actor-filters-context.tsx @@ -0,0 +1,145 @@ +import { faHashtag, faKey } from "@rivet-gg/icons"; +import { useQuery } from "@tanstack/react-query"; +import { useSearch } from "@tanstack/react-router"; +import { CommandGroup, CommandItem } from "cmdk"; +import { createContext, useContext } from "react"; +import { cn } from "../lib/utils"; +import { Checkbox } from "../ui/checkbox"; +import { + createFiltersPicker, + createFiltersRemover, + createFiltersSchema, + type FilterDefinitions, + FilterOp, + type OptionsProviderProps, +} from "../ui/filters"; +import { ActorRegion } from "./actor-region"; +import { ActorStatus } from "./actor-status"; +import { useManager } from "./manager-context"; +import type { ActorStatus as ActorStatusType } from "./queries"; + +export const ACTORS_FILTERS_DEFINITIONS = { + id: { + type: "string", + label: "Actor ID", + icon: faHashtag, + operators: [FilterOp.EQUAL], + excludes: ["key"], + }, + key: { + type: "string", + label: "Actor Key", + icon: faKey, + operators: [FilterOp.EQUAL], + excludes: ["id"], + }, + ...(__APP_TYPE__ === "engine" + ? { + showDestroyed: { + type: "boolean", + label: "Show destroyed", + category: "display", + }, + } + : {}), + showIds: { + type: "boolean", + label: "Show IDs", + category: "display", + ephemeral: true, + }, + // tags: { + // type: "select", + // label: "Tags", + // icon: faTag, + // options: TagsOptions, + // operators: { + // [FilterOp.EQUAL]: "is one of", + // [FilterOp.NOT_EQUAL]: "is not one of", + // }, + // }, + // createdAt: { + // type: "date", + // label: "Created", + // icon: faCalendarCirclePlus, + // }, + // destroyedAt: { + // type: "date", + // label: "Destroyed", + // icon: faCalendarCircleMinus, + // }, + // status: { + // type: "select", + // label: "Status", + // icon: faSignalBars, + // options: StatusOptions, + // display: ({ value }) => { + // if (value.length > 1) { + // return {value.length} statuses; + // } + // return ( + // + // ); + // }, + // }, + // region: { + // type: "select", + // label: "Region", + // icon: faGlobe, + // options: RegionOptions, + // display: ({ value }) => { + // if (value.length > 1) { + // return {value.length} regions; + // } + + // return ; + // }, + // operators: { + // [FilterOp.EQUAL]: "is one of", + // [FilterOp.NOT_EQUAL]: "is not one of", + // }, + // }, + // destroyed: { + // type: "boolean", + // label: "Show destroyed actors", + // icon: faEye, + // }, +} satisfies FilterDefinitions; + +const defaultActorFiltersContextValue = { + definitions: ACTORS_FILTERS_DEFINITIONS, + get pick() { + return createFiltersPicker(this.definitions); + }, + get schema() { + return createFiltersSchema(this.definitions); + }, + get remove() { + return createFiltersRemover(this.definitions); + }, +}; + +export const ActorsFilters = createContext(defaultActorFiltersContextValue); + +export const ActorsFiltersProvider = ActorsFilters.Provider; + +export const useActorsFilters = () => { + const context = useContext(ActorsFilters); + if (!context) { + throw new Error("useActorsFilters must be used within ActorsFilters"); + } + return context; +}; + +export const useFilters = ( + fn: (filters: Record) => any = (state) => state, +): any => { + const { pick } = useActorsFilters(); + return useSearch({ + strict: false, + select: (state) => fn(pick(state)), + }); +}; diff --git a/frontend/src/components/actors/actor-general.tsx b/frontend/src/components/actors/actor-general.tsx new file mode 100644 index 0000000000..098642ec72 --- /dev/null +++ b/frontend/src/components/actors/actor-general.tsx @@ -0,0 +1,133 @@ +import { useQuery } from "@tanstack/react-query"; +import { formatISO } from "date-fns"; +import { cn, Dd, DiscreteCopyButton, Dl, Dt, Flex } from "@/components"; +import { ActorRegion } from "./actor-region"; +import { ActorObjectInspector } from "./console/actor-inspector"; +import { useManager } from "./manager-context"; +import type { ActorId } from "./queries"; + +export interface ActorGeneralProps { + actorId: ActorId; +} + +export function ActorGeneral({ actorId }: ActorGeneralProps) { + const { + data: { + region, + keys, + createdAt, + destroyedAt, + connectableAt, + pendingAllocationAt, + sleepingAt, + crashPolicy, + } = {}, + } = useQuery(useManager().actorGeneralQueryOptions(actorId)); + + return ( +
+

General

+ +
+
Region
+
+ +
+
ID
+
+ + {actorId} + +
+
Keys
+
+ + + +
+
Crash Policy
+
{crashPolicy}
+
Created
+
+ + {createdAt ? formatISO(createdAt) : "n/a"} + +
+
Pending Allocation
+
+ + {pendingAllocationAt + ? formatISO(pendingAllocationAt) + : "n/a"} + +
+
Connectable
+
+ + {connectableAt ? formatISO(connectableAt) : "n/a"} + +
+
Sleeping
+
+ + {sleepingAt ? formatISO(sleepingAt) : "n/a"} + +
+
Destroyed
+
+ + {destroyedAt ? formatISO(destroyedAt) : "n/a"} + +
+
+
+
+ ); +} diff --git a/frontend/src/components/actors/actor-logs-tab.tsx b/frontend/src/components/actors/actor-logs-tab.tsx new file mode 100644 index 0000000000..40f1fb8a3f --- /dev/null +++ b/frontend/src/components/actors/actor-logs-tab.tsx @@ -0,0 +1,91 @@ +import { startTransition, useState } from "react"; +import { LogsView, ToggleGroup, ToggleGroupItem } from "@/components"; +import type { ActorAtom } from "./actor-context"; +import { ActorDetailsSettingsButton } from "./actor-details-settings-button"; +import { ActorDownloadLogsButton } from "./actor-download-logs-button"; +import { ActorLogs, type LogsTypeFilter } from "./actor-logs"; +import type { ActorId } from "./queries"; + +interface ActorLogsTabProps { + actorId: ActorId; +} + +export function ActorLogsTab({ actorId }: ActorLogsTabProps) { + const [search, setSearch] = useState(""); + const [logsFilter, setLogsFilter] = useState("all"); + + return ( +
+
+
+
+ + startTransition(() => setSearch(e.target.value)) + } + /> +
+ { + if (!value) { + setLogsFilter("all"); + } else { + setLogsFilter(value as LogsTypeFilter); + } + }} + className="gap-0 text-xs p-2 border-r" + > + + all + + + output + + + errors + + + + +
+
+
+ +
+
+ ); +} + +ActorLogsTab.Skeleton = () => { + return ( +
+ +
+ ); +}; diff --git a/frontend/src/components/actors/actor-logs.tsx b/frontend/src/components/actors/actor-logs.tsx new file mode 100644 index 0000000000..d677406242 --- /dev/null +++ b/frontend/src/components/actors/actor-logs.tsx @@ -0,0 +1,218 @@ +import { useQuery } from "@tanstack/react-query"; +import type { Virtualizer } from "@tanstack/react-virtual"; +import { memo, useCallback, useEffect, useRef } from "react"; +import { useResizeObserver } from "usehooks-ts"; +import { ShimmerLine, VirtualScrollArea } from "@/components"; +import { useActorDetailsSettings } from "./actor-details-settings"; +import { ActorConsoleMessage } from "./console/actor-console-message"; +import { useManager } from "./manager-context"; +import type { ActorId, ActorLogEntry } from "./queries"; + +export type LogsTypeFilter = "all" | "output" | "errors"; + +interface ActorLogsProps { + actorId: ActorId; + typeFilter?: LogsTypeFilter; + filter?: string; +} + +export const ActorLogs = memo( + ({ typeFilter, actorId, filter }: ActorLogsProps) => { + const [settings] = useActorDetailsSettings(); + const follow = useRef(true); + const shouldFollow = () => settings.autoFollowLogs && follow.current; + + const viewport = useRef(null); + const virtualizer = useRef>(null); + // Detect if the container has resized (i.e, console was opened) + useResizeObserver({ + ref: viewport, + onResize: () => { + if (shouldFollow()) { + // https://github.com/TanStack/virtual/issues/537 + requestAnimationFrame(() => { + virtualizer.current?.scrollToIndex(combined.length, { + align: "end", + }); + }); + } + }, + }); + + const { data: status } = useQuery( + useManager().actorStatusQueryOptions(actorId), + ); + const { + data: logs = [], + isFetching, + isError, + } = useQuery(useManager().actorLogsQueryOptions(actorId)); + + const combined = filterLogs({ + typeFilter: typeFilter ?? "all", + filter: filter ?? "", + logs: logs ?? [], + }); + + // Scroll to the bottom when new logs are added + // biome-ignore lint/correctness/useExhaustiveDependencies: run this effect only when the length of the logs changes + useEffect(() => { + if (!shouldFollow()) { + return () => {}; + } + // https://github.com/TanStack/virtual/issues/537 + const rafId = requestAnimationFrame(() => { + virtualizer.current?.scrollToIndex( + virtualizer.current.options.count - 1, + { + align: "end", + }, + ); + }); + + return () => { + cancelAnimationFrame(rafId); + }; + }, [combined.length]); + + // Detect if the user has scrolled all the way to the bottom + const handleChange = useCallback( + (instance: Virtualizer, sync: boolean) => { + if (sync) { + return; + } + + follow.current = + !instance.isScrolling && + instance.range?.endIndex === instance.options.count - 1; + }, + [], + ); + + if (status === "starting" && combined.length === 0) { + return ( +
+ + [SYSTEM]: Actor is starting... + +
+ ); + } + + if (isFetching) { + return ( + <> + +
+ + Loading logs... + +
+ + ); + } + + if (combined.length === 0) { + if (isError) { + return ( +
+ + [SYSTEM]: Couldn't find the logs. Please try again + later. + +
+ ); + } + return ( +
+ + [SYSTEM]: No logs found. Logs are retained for 3 days. + +
+ ); + } + + return ( + <> + + ({ + ...combined[index], + children: combined[index].message, + variant: combined[index].level as + | "debug" + | "error" + | "info", + timestamp: settings.showTimestamps + ? combined[index].timestamp + ? new Date(combined[index].timestamp) + : undefined + : undefined, + })} + onChange={handleChange} + count={combined.length} + estimateSize={() => 26} + row={ActorConsoleMessage} + /> + + ); + }, +); + +interface ScrollerProps { + virtualizer: React.MutableRefObject | null>; +} + +function Scroller({ virtualizer }: ScrollerProps) { + // biome-ignore lint/correctness/useExhaustiveDependencies: scroll on mount, no need to run this effect again + useEffect(() => { + // https://github.com/TanStack/virtual/issues/537 + virtualizer.current?.scrollToIndex( + virtualizer.current.options.count - 1, + { + align: "end", + }, + ); + }, []); + + return null; +} + +export function filterLogs({ + typeFilter, + filter, + logs, +}: { + typeFilter: LogsTypeFilter; + filter: string; + logs: ActorLogEntry[]; +}) { + const output = logs?.filter((log) => { + if (typeFilter === "errors") { + return log.level === "error"; + } + if (typeFilter === "output") { + return log.level !== "error"; + } + return true; + }); + + // Search + const filtered = + filter && filter.trim() !== "" + ? output.filter((log) => log.message.includes(filter)) + : output; + + const sorted = filtered.toSorted( + (a, b) => + new Date(a.timestamp).valueOf() - new Date(b.timestamp).valueOf(), + ); + + return sorted; +} diff --git a/frontend/src/components/actors/actor-memory-stats.tsx b/frontend/src/components/actors/actor-memory-stats.tsx new file mode 100644 index 0000000000..f2af24d75d --- /dev/null +++ b/frontend/src/components/actors/actor-memory-stats.tsx @@ -0,0 +1,137 @@ +import { format } from "date-fns"; +import { filesize } from "filesize"; +import { useId } from "react"; +import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from "recharts"; +import { timing } from "../lib/timing"; +import { + type ChartConfig, + ChartContainer, + ChartTooltip, + ChartTooltipContent, +} from "../ui/chart"; + +interface ActorMemoryStatsProps { + metricsAt: number; + memory: number[]; + allocatedMemory?: number; + syncId?: string; + interval?: number; + isRunning?: boolean; +} + +const chartConfig = { + value: { + color: "hsl(var(--chart-1))", + label: "Memory Usage", + }, +} satisfies ChartConfig; + +export function ActorMemoryStats({ + interval = 15, + memory, + allocatedMemory, + metricsAt, + syncId, + isRunning = true, +}: ActorMemoryStatsProps) { + // Filter out trailing zeros in the last 15 seconds only if actor is still running + let filteredMemory = [...memory]; + if (isRunning) { + const secondsToCheck = 15; + const pointsToCheck = Math.ceil(secondsToCheck / interval); + + // Find the last non-zero value and cut off any zeros after it + for ( + let i = filteredMemory.length - 1; + i >= Math.max(0, filteredMemory.length - pointsToCheck); + i-- + ) { + if (filteredMemory[i] === 0) { + filteredMemory = filteredMemory.slice(0, i); + } else { + break; + } + } + } + + const data = filteredMemory.map((value, i) => ({ + x: `${(filteredMemory.length - i) * -interval}`, + value, + config: { + label: new Date( + metricsAt - + (filteredMemory.length - i) * timing.seconds(interval), + ), + }, + })); + + const max = allocatedMemory || Math.max(...filteredMemory); + + const id = useId(); + + const fillId = `fill-${id}`; + return ( + + + + + + `${Math.ceil((value / max) * 100)}%` + } + /> + { + return format(label, "HH:mm:ss"); + }} + valueFormatter={(value) => { + if (typeof value !== "number") { + return "n/a"; + } + return `${filesize(value)} (${Math.round((value / max) * 100).toFixed(2)}%)`; + }} + /> + } + /> + + + + + + + + + + ); +} diff --git a/frontend/src/components/actors/actor-metrics-tab.tsx b/frontend/src/components/actors/actor-metrics-tab.tsx new file mode 100644 index 0000000000..9fa2eb4fc0 --- /dev/null +++ b/frontend/src/components/actors/actor-metrics-tab.tsx @@ -0,0 +1,25 @@ +import { faBooks, Icon } from "@rivet-gg/icons"; +import { Button, ScrollArea } from "@/components"; +import { ActorMetrics } from "./actor-metrics"; +import type { ActorId } from "./queries"; + +interface ActorMetricsTabProps { + actorId: ActorId; +} + +export function ActorMetricsTab(props: ActorMetricsTabProps) { + return ( + +
+ +
+ +
+ ); +} diff --git a/frontend/src/components/actors/actor-metrics.tsx b/frontend/src/components/actors/actor-metrics.tsx new file mode 100644 index 0000000000..b941f45dd8 --- /dev/null +++ b/frontend/src/components/actors/actor-metrics.tsx @@ -0,0 +1,705 @@ +import { useQuery } from "@tanstack/react-query"; +import { useMemo, useState } from "react"; +import { Button, Dd, Dl, Dt, Flex } from "@/components"; +import type { ActorId } from "./queries"; + +const timeWindowOptions = [ + { label: "5 minutes", value: "5m", milliseconds: 5 * 60 * 1000 }, + { label: "15 minutes", value: "15m", milliseconds: 15 * 60 * 1000 }, + { label: "30 minutes", value: "30m", milliseconds: 30 * 60 * 1000 }, + { label: "1 hour", value: "1h", milliseconds: 60 * 60 * 1000 }, + { label: "3 hours", value: "3h", milliseconds: 3 * 60 * 60 * 1000 }, + { label: "6 hours", value: "6h", milliseconds: 6 * 60 * 60 * 1000 }, + { label: "12 hours", value: "12h", milliseconds: 12 * 60 * 60 * 1000 }, + { label: "24 hours", value: "24h", milliseconds: 24 * 60 * 60 * 1000 }, + { label: "2 days", value: "2d", milliseconds: 2 * 24 * 60 * 60 * 1000 }, +]; + +export interface ActorMetricsProps { + actorId: ActorId; +} + +export function ActorMetrics({ actorId }: ActorMetricsProps) { + // const { data: status } = useQuery(actorStatusQueryOptions(actorId)); + // const { + // data: metricsData, + // isLoading, + // isError, + // } = useQuery(actorMetricsQueryOptions(actorId)); + + // const [showAdvanced, setShowAdvanced] = useState(false); + + // const timeWindowMs = useAtomValue(actorMetricsTimeWindowAtom); + // const setTimeWindowMs = useSetAtom(actorMetricsTimeWindowAtom); + // const environment = useAtomValue(actorEnvironmentAtom); + + // const currentTimeWindow = + // timeWindowOptions.find( + // (option) => option.milliseconds === timeWindowMs, + // ) || timeWindowOptions[1]; + // const [timeWindow, setTimeWindow] = useState(currentTimeWindow.value); + + // const isActorRunning = status === "running"; + + // // Create a query for time window-specific metrics + // const { data: customMetricsData, status: customMetricsStatus } = useQuery({ + // ...actorMetricsQueryOptions( + // { + // projectNameId: environment?.projectNameId || "", + // environmentNameId: environment?.environmentNameId || "", + // actorId: id, + // timeWindowMs: timeWindowMs, + // }, + // { refetchInterval: 5000 }, + // ), + // enabled: !!environment && !!id, + // }); + + // // Use custom metrics if available, otherwise fall back to default + // const metricsData = customMetricsData + // ? { + // metrics: customMetricsData.metrics, + // rawData: customMetricsData.rawData, + // interval: customMetricsData.interval, + // status: customMetricsStatus, + // updatedAt: Date.now(), + // } + // : defaultMetricsData; + + // const handleTimeWindowChange = (value: string) => { + // setTimeWindow(value); + // const selectedOption = timeWindowOptions.find( + // (option) => option.value === value, + // ); + // if (selectedOption) { + // setTimeWindowMs(selectedOption.milliseconds); + // } + // }; + + // const formatBytes = (bytes: number | null | undefined) => { + // if (!isActorRunning || bytes === null || bytes === undefined) + // return "n/a"; + // const mb = bytes / 1024 / 1024; + // if (mb < 1024) { + // return `${mb.toFixed(1)} MB`; + // } + // return `${(mb / 1024).toFixed(1)} GB`; + // }; + + // const formatCpuUsage = (cpu: number | null | undefined) => { + // if (!isActorRunning || cpu === null || cpu === undefined) return "n/a"; + // return `${(cpu * 100).toFixed(2)}%`; + // }; + + // const formatNumber = (value: number | null | undefined) => { + // if (!isActorRunning || value === null || value === undefined) + // return "n/a"; + // return value.toLocaleString(); + // }; + + // const formatTimestamp = (timestamp: number | null | undefined) => { + // if (!isActorRunning || timestamp === null || timestamp === undefined) + // return "n/a"; + // return new Date(timestamp * 1000).toLocaleString(); + // }; + + // // Calculate CPU percentage using time series data points + // const cpuPercentage = useMemo(() => { + // if (!isActorRunning) { + // return "Stopped"; + // } + + // const data = metricsData; + // if (!data || !data.rawData || !data.interval) { + // return "n/a"; + // } + + // const cpuValues = data.rawData.cpu_usage_seconds_total; + // if (!cpuValues || cpuValues.length < 2) { + // return "n/a"; + // } + + // // Find the last valid CPU rate from the most recent data points + // let cpuRate = 0; + // for (let i = cpuValues.length - 1; i > 0; i--) { + // const currentCpu = cpuValues[i]; + // const previousCpu = cpuValues[i - 1]; + + // if ( + // currentCpu !== 0 && + // previousCpu !== 0 && + // currentCpu >= previousCpu + // ) { + // const cpuDelta = currentCpu - previousCpu; + // const timeDelta = data.interval / 1000; // Convert ms to seconds + + // // Rate calculation: CPU seconds used per second of real time + // // This gives the fraction of available CPU used (0-1) + // cpuRate = (cpuDelta / timeDelta) * 100; + // break; + // } + // } + + // return `${Math.min(cpuRate, 100).toFixed(2)}%`; + // }, [metricsData, isActorRunning]); + + // const calculateMemoryPercentage = (usage: number | null | undefined) => { + // if ( + // !isActorRunning || + // usage === null || + // usage === undefined || + // !resources || + // !resources.memory || + // resources.memory === 0 + // ) { + // return null; + // } + // // Convert usage from bytes to MB and compare with resources.memory (which is in MB) + // const usageMB = usage / (1024 * 1024); + // return (usageMB / resources.memory) * 100; + // }; + + // const data = metricsData?.metrics || {}; + + // if (isLoading) { + // return ( + //
+ //

Metrics

+ //
Loading...
+ //
+ // ); + // } + + // if (isError) { + // return ( + //
+ //

Metrics

+ //
+ // Error loading metrics + //
+ //
+ // ); + // } + + // const memoryPercentage = calculateMemoryPercentage(data.memory_usage_bytes); + + // return ( + //
+ //
+ //

Container Metrics

+ // + //
+ + // {/* Main Metrics */} + //
+ //
+ //
+ //
CPU Usage
+ //
+ // {cpuPercentage} + // {metricsData.rawData?.cpu_usage_seconds_total && + // metricsData.rawData.cpu_usage_seconds_total.length > + // 0 ? ( + // + // ) : null} + //
+ //
+ //
+ //
Memory Usage
+ //
+ // + // {formatBytes(data.memory_usage_bytes)} + // {memoryPercentage !== null && ( + // + // ({memoryPercentage.toFixed(1)}%) + // + // )} + // + // {metricsData.rawData?.memory_usage_bytes && + // metricsData.rawData.memory_usage_bytes.length > + // 0 ? ( + // + // ) : null} + //
+ //
+ //
+ //
+ + // {/* Advanced Metrics */} + // {false && ( + // + // {/* CPU & Performance */} + //
+ //

CPU & Performance

+ //
+ //
CPU Load Average (10s)
+ //
{formatCpuUsage(data.cpu_load_average_10s)}
+ //
CPU Usage Seconds Total
+ //
+ // {formatNumber(data.cpu_usage_seconds_total)} + //
+ //
CPU User Seconds Total
+ //
{formatNumber(data.cpu_user_seconds_total)}
+ //
CPU System Seconds Total
+ //
+ // {formatNumber(data.cpu_system_seconds_total)} + //
+ //
CPU Schedstat Run Periods
+ //
+ // {formatNumber( + // data.cpu_schedstat_run_periods_total, + // )} + //
+ //
CPU Schedstat Run Seconds
+ //
+ // {formatNumber( + // data.cpu_schedstat_run_seconds_total, + // )} + //
+ //
CPU Schedstat Runqueue Seconds
+ //
+ // {formatNumber( + // data.cpu_schedstat_runqueue_seconds_total, + // )} + //
+ //
+ //
+ + // {/* Memory */} + //
+ //

Memory

+ //
+ //
Memory Usage
+ //
{formatBytes(data.memory_usage_bytes)}
+ //
Memory Working Set
+ //
+ // {formatBytes(data.memory_working_set_bytes)} + //
+ //
Memory RSS
+ //
{formatBytes(data.memory_rss)}
+ //
Memory Cache
+ //
{formatBytes(data.memory_cache)}
+ //
Memory Swap
+ //
{formatBytes(data.memory_swap)}
+ //
Memory Max Usage
+ //
{formatBytes(data.memory_max_usage_bytes)}
+ //
Memory Mapped File
+ //
{formatBytes(data.memory_mapped_file)}
+ //
Memory Failcnt
+ //
{formatNumber(data.memory_failcnt)}
+ //
+ //
+ + // {/* Memory Failures */} + //
+ //

Memory Failures

+ //
+ //
Page Fault (Container)
+ //
+ // {formatNumber( + // data.memory_failures_pgfault_container, + // )} + //
+ //
Page Fault (Hierarchy)
+ //
+ // {formatNumber( + // data.memory_failures_pgfault_hierarchy, + // )} + //
+ //
Major Page Fault (Container)
+ //
+ // {formatNumber( + // data.memory_failures_pgmajfault_container, + // )} + //
+ //
Major Page Fault (Hierarchy)
+ //
+ // {formatNumber( + // data.memory_failures_pgmajfault_hierarchy, + // )} + //
+ //
+ //
+ + // {/* Resource Limits */} + //
+ //

Resource Limits

+ //
+ //
Memory Limit
+ //
+ // {resources?.memory + // ? `${resources.memory} MB` + // : "n/a"} + //
+ //
CPU Limit
+ //
+ // {resources?.cpu + // ? `${resources.cpu / 1000} cores` + // : "n/a"} + //
+ //
+ //
+ + // {/* Processes & Threads */} + //
+ //

+ // Processes & Threads + //

+ //
+ //
Processes
+ //
{formatNumber(data.processes)}
+ //
Threads
+ //
{formatNumber(data.threads)}
+ //
Max Threads
+ //
{formatNumber(data.threads_max)}
+ //
Tasks Running
+ //
{formatNumber(data.tasks_state_running)}
+ //
Tasks Sleeping
+ //
{formatNumber(data.tasks_state_sleeping)}
+ //
Tasks Stopped
+ //
{formatNumber(data.tasks_state_stopped)}
+ //
Tasks IO Waiting
+ //
{formatNumber(data.tasks_state_iowaiting)}
+ //
Tasks Uninterruptible
+ //
+ // {formatNumber(data.tasks_state_uninterruptible)} + //
+ //
+ //
+ + // {/* Filesystem */} + //
+ //

Filesystem

+ //
+ //
Reads Bytes Total (sda)
+ //
+ // {formatBytes(data.fs_reads_bytes_total_sda)} + //
+ //
Writes Bytes Total (sda)
+ //
+ // {formatBytes(data.fs_writes_bytes_total_sda)} + //
+ //
+ //
+ + // {/* Network - Receive */} + //
+ //

Network - Receive

+ //
+ //
Bytes Total (eth0)
+ //
+ // {formatBytes( + // data.network_receive_bytes_total_eth0, + // )} + //
+ //
Bytes Total (eth1)
+ //
+ // {formatBytes( + // data.network_receive_bytes_total_eth1, + // )} + //
+ //
Errors Total (eth0)
+ //
+ // {formatNumber( + // data.network_receive_errors_total_eth0, + // )} + //
+ //
Errors Total (eth1)
+ //
+ // {formatNumber( + // data.network_receive_errors_total_eth1, + // )} + //
+ //
Packets Dropped (eth0)
+ //
+ // {formatNumber( + // data.network_receive_packets_dropped_total_eth0, + // )} + //
+ //
Packets Dropped (eth1)
+ //
+ // {formatNumber( + // data.network_receive_packets_dropped_total_eth1, + // )} + //
+ //
Packets Total (eth0)
+ //
+ // {formatNumber( + // data.network_receive_packets_total_eth0, + // )} + //
+ //
Packets Total (eth1)
+ //
+ // {formatNumber( + // data.network_receive_packets_total_eth1, + // )} + //
+ //
+ //
+ + // {/* Network - Transmit */} + //
+ //

Network - Transmit

+ //
+ //
Bytes Total (eth0)
+ //
+ // {formatBytes( + // data.network_transmit_bytes_total_eth0, + // )} + //
+ //
Bytes Total (eth1)
+ //
+ // {formatBytes( + // data.network_transmit_bytes_total_eth1, + // )} + //
+ //
Errors Total (eth0)
+ //
+ // {formatNumber( + // data.network_transmit_errors_total_eth0, + // )} + //
+ //
Errors Total (eth1)
+ //
+ // {formatNumber( + // data.network_transmit_errors_total_eth1, + // )} + //
+ //
Packets Dropped (eth0)
+ //
+ // {formatNumber( + // data.network_transmit_packets_dropped_total_eth0, + // )} + //
+ //
Packets Dropped (eth1)
+ //
+ // {formatNumber( + // data.network_transmit_packets_dropped_total_eth1, + // )} + //
+ //
Packets Total (eth0)
+ //
+ // {formatNumber( + // data.network_transmit_packets_total_eth0, + // )} + //
+ //
Packets Total (eth1)
+ //
+ // {formatNumber( + // data.network_transmit_packets_total_eth1, + // )} + //
+ //
+ //
+ + // {/* TCP Connections */} + //
+ //

TCP Connections

+ //
+ //
Close
+ //
+ // {formatNumber(data.network_tcp_usage_close)} + //
+ //
Close Wait
+ //
+ // {formatNumber(data.network_tcp_usage_closewait)} + //
+ //
Closing
+ //
+ // {formatNumber(data.network_tcp_usage_closing)} + //
+ //
Established
+ //
+ // {formatNumber( + // data.network_tcp_usage_established, + // )} + //
+ //
Fin Wait 1
+ //
+ // {formatNumber(data.network_tcp_usage_finwait1)} + //
+ //
Fin Wait 2
+ //
+ // {formatNumber(data.network_tcp_usage_finwait2)} + //
+ //
Last Ack
+ //
+ // {formatNumber(data.network_tcp_usage_lastack)} + //
+ //
Listen
+ //
+ // {formatNumber(data.network_tcp_usage_listen)} + //
+ //
Syn Recv
+ //
+ // {formatNumber(data.network_tcp_usage_synrecv)} + //
+ //
Syn Sent
+ //
+ // {formatNumber(data.network_tcp_usage_synsent)} + //
+ //
Time Wait
+ //
+ // {formatNumber(data.network_tcp_usage_timewait)} + //
+ //
+ //
+ + // {/* TCP6 Connections */} + //
+ //

TCP6 Connections

+ //
+ //
Close
+ //
+ // {formatNumber(data.network_tcp6_usage_close)} + //
+ //
Close Wait
+ //
+ // {formatNumber( + // data.network_tcp6_usage_closewait, + // )} + //
+ //
Closing
+ //
+ // {formatNumber(data.network_tcp6_usage_closing)} + //
+ //
Established
+ //
+ // {formatNumber( + // data.network_tcp6_usage_established, + // )} + //
+ //
Fin Wait 1
+ //
+ // {formatNumber(data.network_tcp6_usage_finwait1)} + //
+ //
Fin Wait 2
+ //
+ // {formatNumber(data.network_tcp6_usage_finwait2)} + //
+ //
Last Ack
+ //
+ // {formatNumber(data.network_tcp6_usage_lastack)} + //
+ //
Listen
+ //
+ // {formatNumber(data.network_tcp6_usage_listen)} + //
+ //
Syn Recv
+ //
+ // {formatNumber(data.network_tcp6_usage_synrecv)} + //
+ //
Syn Sent
+ //
+ // {formatNumber(data.network_tcp6_usage_synsent)} + //
+ //
Time Wait
+ //
+ // {formatNumber(data.network_tcp6_usage_timewait)} + //
+ //
+ //
+ + // {/* UDP Connections */} + //
+ //

UDP Connections

+ //
+ //
Dropped
+ //
+ // {formatNumber(data.network_udp_usage_dropped)} + //
+ //
Listen
+ //
+ // {formatNumber(data.network_udp_usage_listen)} + //
+ //
RX Queued
+ //
+ // {formatNumber(data.network_udp_usage_rxqueued)} + //
+ //
TX Queued
+ //
+ // {formatNumber(data.network_udp_usage_txqueued)} + //
+ //
+ //
+ + // {/* UDP6 Connections */} + //
+ //

UDP6 Connections

+ //
+ //
Dropped
+ //
+ // {formatNumber(data.network_udp6_usage_dropped)} + //
+ //
Listen
+ //
+ // {formatNumber(data.network_udp6_usage_listen)} + //
+ //
RX Queued
+ //
+ // {formatNumber(data.network_udp6_usage_rxqueued)} + //
+ //
TX Queued
+ //
+ // {formatNumber(data.network_udp6_usage_txqueued)} + //
+ //
+ //
+ + // {/* System */} + //
+ //

System

+ //
+ //
File Descriptors
+ //
{formatNumber(data.file_descriptors)}
+ //
Sockets
+ //
{formatNumber(data.sockets)}
+ //
Last Seen
+ //
{formatTimestamp(data.last_seen)}
+ //
Start Time
+ //
{formatTimestamp(data.start_time_seconds)}
+ //
+ //
+ //
+ // )} + //
+ // ); + return null; +} diff --git a/frontend/src/components/actors/actor-network.tsx b/frontend/src/components/actors/actor-network.tsx new file mode 100644 index 0000000000..ae96fc1e14 --- /dev/null +++ b/frontend/src/components/actors/actor-network.tsx @@ -0,0 +1,143 @@ +import { faBooks, Icon } from "@rivet-gg/icons"; +import { useQuery } from "@tanstack/react-query"; +import { Fragment } from "react"; +import { + Button, + cn, + Dd, + DiscreteCopyButton, + Dl, + DocsSheet, + Dt, + Flex, +} from "@/components"; +import { ActorObjectInspector } from "./console/actor-inspector"; +import { useManager } from "./manager-context"; +import type { ActorId } from "./queries"; + +export interface ActorNetworkProps { + actorId: ActorId; +} + +export function ActorNetwork({ actorId }: ActorNetworkProps) { + const { data: ports } = useQuery( + useManager().actorNetworkPortsQueryOptions(actorId), + ); + if (!ports) { + return null; + } + + return ( +
+
+

Network

+ + + +
+
+ +
+
Ports
+
+ {Object.entries(ports).map( + ([name, port], index) => ( + + + {name} + +
+
Protocol
+
+ + {port.protocol} + +
+
Port
+
+ + {port.port} + +
+
Hostname
+
+ + + {port.hostname} + + +
+ {port.url ? ( + <> +
URL
+
+ + + {port.url} + + +
+ + ) : null} + + {port.routing?.host ? ( + <> +
Host Routing
+
+ + + +
+ + ) : null} +
+
+ ), + )} +
+
+
+
+
+ ); +} diff --git a/frontend/src/components/actors/actor-not-found.tsx b/frontend/src/components/actors/actor-not-found.tsx new file mode 100644 index 0000000000..87cda8ab3d --- /dev/null +++ b/frontend/src/components/actors/actor-not-found.tsx @@ -0,0 +1,76 @@ +import { faQuestionSquare, Icon } from "@rivet-gg/icons"; +import { useQuery } from "@tanstack/react-query"; +import { useNavigate } from "@tanstack/react-router"; +import { ShimmerLine } from "../shimmer-line"; +import { Button } from "../ui/button"; +import { FilterOp } from "../ui/filters"; +import { ActorTabs } from "./actors-actor-details"; +import { useActorsView } from "./actors-view-context-provider"; +import { useManager } from "./manager-context"; +import type { ActorFeature, ActorId } from "./queries"; + +export function ActorNotFound({ + actorId, + features = [], +}: { + features?: ActorFeature[]; + actorId?: ActorId; +}) { + const { copy } = useActorsView(); + + const navigate = useNavigate(); + + const hasDevMode = false; + + const { isLoading } = useQuery({ + // biome-ignore lint/style/noNonNullAssertion: enabled guarantees actorId is defined + ...useManager().actorQueryOptions(actorId!), + enabled: !!actorId, + }); + + return ( +
+ +
+ {!isLoading ? ( + <> + +

+ {copy.actorNotFound} +

+

+ {copy.actorNotFoundDescription} +

+ + ) : null} + + {!hasDevMode && !isLoading ? ( + + ) : null} + {isLoading ? : null} +
+
+
+ ); +} diff --git a/frontend/src/components/actors/actor-queries-context.tsx b/frontend/src/components/actors/actor-queries-context.tsx new file mode 100644 index 0000000000..df74b02f2e --- /dev/null +++ b/frontend/src/components/actors/actor-queries-context.tsx @@ -0,0 +1,223 @@ +import { createActorInspectorClient } from "@rivetkit/core/inspector"; +import { queryOptions } from "@tanstack/react-query"; +import { createContext, useContext } from "react"; +import type { ActorId } from "./queries"; + +type RequestOptions = Parameters[1]; + +export const defaultActorContext = { + createActorInspectorFetchConfiguration: ( + actorId: ActorId | string, + ): RequestOptions => ({ + headers: { + "X-RivetKit-Query": JSON.stringify({ + getForId: { actorId }, + }), + }, + }), + createActorInspectorUrl(actorId: ActorId | string) { + return "http://localhost:6420/registry/actors/inspect"; + }, + createActorInspector(actorId: ActorId | string) { + return createActorInspectorClient( + this.createActorInspectorUrl(actorId), + this.createActorInspectorFetchConfiguration(actorId), + ); + }, + actorPingQueryOptions( + actorId: ActorId, + opts: { enabled?: boolean; refetchInterval?: number | false } = {}, + ) { + return queryOptions({ + enabled: false, + refetchInterval: 1000, + ...opts, + queryKey: ["actor", actorId, "ping"], + queryFn: async ({ queryKey: [, actorId] }) => { + const client = this.createActorInspector(actorId); + const response = await client.ping.$get(); + if (!response.ok) { + throw response; + } + return await response.json(); + }, + }); + }, + + actorStateQueryOptions( + actorId: ActorId, + { enabled }: { enabled: boolean } = { enabled: true }, + ) { + return queryOptions({ + enabled, + refetchInterval: 1000, + queryKey: ["actor", actorId, "state"], + queryFn: async ({ queryKey: [, actorId] }) => { + const client = this.createActorInspector(actorId); + const response = await client.state.$get(); + + if (!response.ok) { + throw response; + } + return (await response.json()) as { + enabled: boolean; + state: unknown; + }; + }, + }); + }, + + actorConnectionsQueryOptions( + actorId: ActorId, + { enabled }: { enabled: boolean } = { enabled: true }, + ) { + return queryOptions({ + enabled, + refetchInterval: 1000, + queryKey: ["actor", actorId, "connections"], + queryFn: async ({ queryKey: [, actorId] }) => { + const client = this.createActorInspector(actorId); + const response = await client.connections.$get(); + + if (!response.ok) { + throw response; + } + return await response.json(); + }, + }); + }, + + actorDatabaseQueryOptions( + actorId: ActorId, + { enabled }: { enabled: boolean } = { enabled: true }, + ) { + return queryOptions({ + enabled, + queryKey: ["actor", actorId, "database"], + queryFn: async ({ queryKey: [, actorId] }) => { + const client = this.createActorInspector(actorId); + const response = await client.db.$get(); + + if (!response.ok) { + throw response; + } + return await response.json(); + }, + }); + }, + + actorDatabaseEnabledQueryOptions( + actorId: ActorId, + { enabled }: { enabled: boolean } = { enabled: true }, + ) { + return queryOptions({ + ...this.actorDatabaseQueryOptions(actorId, { enabled }), + select: (data) => data.enabled, + notifyOnChangeProps: ["data", "isError", "isLoading"], + }); + }, + + actorDatabaseTablesQueryOptions( + actorId: ActorId, + { enabled }: { enabled: boolean } = { enabled: true }, + ) { + return queryOptions({ + ...this.actorDatabaseQueryOptions(actorId, { enabled }), + select: (data) => + data.db?.map((table) => ({ + name: table.table.name, + type: table.table.type, + records: table.records, + })) || [], + notifyOnChangeProps: ["data", "isError", "isLoading"], + }); + }, + + actorDatabaseRowsQueryOptions( + actorId: ActorId, + table: string, + { enabled }: { enabled: boolean } = { enabled: true }, + ) { + return queryOptions({ + enabled, + staleTime: 0, + gcTime: 5000, + queryKey: ["actor", actorId, "database", table], + queryFn: async ({ queryKey: [, actorId, , table] }) => { + const client = this.createActorInspector(actorId); + const response = await client.db.$post({ + json: { query: `SELECT * FROM ${table} LIMIT 500` }, + }); + if (!response.ok) { + throw response; + } + return await response.json(); + }, + }); + }, + + actorEventsQueryOptions( + actorId: ActorId, + { enabled }: { enabled: boolean } = { enabled: true }, + ) { + return queryOptions({ + enabled, + refetchInterval: 1000, + queryKey: ["actor", actorId, "events"], + queryFn: async ({ queryKey: [, actorId] }) => { + const client = this.createActorInspector(actorId); + const response = await client.events.$get(); + + if (!response.ok) { + throw response; + } + return await response.json(); + }, + }); + }, + + actorRpcsQueryOptions( + actorId: ActorId, + { enabled }: { enabled: boolean } = { enabled: true }, + ) { + return queryOptions({ + enabled, + queryKey: ["actor", actorId, "rpcs"], + queryFn: async ({ queryKey: [, actorId] }) => { + const client = this.createActorInspector(actorId); + const response = await client.rpcs.$get(); + + if (!response.ok) { + throw response; + } + return await response.json(); + }, + }); + }, + + actorClearEventsMutationOptions(actorId: ActorId) { + return { + mutationKey: ["actor", actorId, "clear-events"], + mutationFn: async () => { + const client = this.createActorInspector(actorId); + const response = await client.events.clear.$post(); + if (!response.ok) { + throw response; + } + return await response.json(); + }, + }; + }, +}; + +export type ActorContext = typeof defaultActorContext; + +export function createDefaultActorContext(): ActorContext { + return defaultActorContext; +} + +const ActorContext = createContext({} as ActorContext); + +export const useActor = () => useContext(ActorContext); + +export const ActorProvider = ActorContext.Provider; diff --git a/frontend/src/components/actors/actor-region.tsx b/frontend/src/components/actors/actor-region.tsx new file mode 100644 index 0000000000..9b07fd534f --- /dev/null +++ b/frontend/src/components/actors/actor-region.tsx @@ -0,0 +1,59 @@ +import { useQuery } from "@tanstack/react-query"; +import { Flex, WithTooltip } from "@/components"; +import { + getRegionKey, + REGION_LABEL, + RegionIcon, +} from "../matchmaker/lobby-region"; +import { useManager } from "./manager-context"; + +interface ActorRegionProps { + regionId?: string; + showLabel?: boolean | "abbreviated"; + className?: string; +} + +export function ActorRegion({ + showLabel, + regionId, + className, +}: ActorRegionProps) { + const { data: region } = useQuery( + useManager().regionQueryOptions(regionId), + ); + + if (!regionId || !region) { + return null; + } + + const regionKey = getRegionKey(region?.id); + + if (showLabel) { + return ( + + + + {showLabel === "abbreviated" + ? regionKey.toUpperCase() + : (REGION_LABEL[regionKey] ?? REGION_LABEL.unknown)} + + + ); + } + + return ( + + + + } + /> + ); +} diff --git a/frontend/src/components/actors/actor-runtime.tsx b/frontend/src/components/actors/actor-runtime.tsx new file mode 100644 index 0000000000..a895671630 --- /dev/null +++ b/frontend/src/components/actors/actor-runtime.tsx @@ -0,0 +1,79 @@ +import { useQuery } from "@tanstack/react-query"; +import { Suspense } from "react"; +import { formatDuration } from "../lib/formatter"; +import { toRecord } from "../lib/utils"; +import { Flex } from "../ui/flex"; +import { Skeleton } from "../ui/skeleton"; +import { Dd, Dl, Dt } from "../ui/typography"; +import { ActorBuild } from "./actor-build"; +import { ACTOR_FRAMEWORK_TAG_VALUE } from "./actor-tags"; +import { ActorObjectInspector } from "./console/actor-inspector"; +import { useManager } from "./manager-context"; +import { ActorFeature, type ActorId } from "./queries"; + +export interface ActorRuntimeProps { + actorId: ActorId; +} + +export function ActorRuntime({ actorId }: ActorRuntimeProps) { + const { data: { lifecycle, resources, runtime, tags } = {} } = useQuery( + useManager().actorRuntimeQueryOptions(actorId), + ); + + const { data: features = [] } = useQuery( + useManager().actorFeaturesQueryOptions(actorId), + ); + + return ( + <> + {features.includes(ActorFeature.Runtime) && lifecycle && runtime ? ( +
+
+

Runtime

+
+ +
+
Kill timeout
+
+ {formatDuration(lifecycle.killTimeout || 0, { + show0Min: true, + })} +
+ {toRecord(tags).framework !== + ACTOR_FRAMEWORK_TAG_VALUE && resources ? ( + <> +
Resources
+
+ {resources.cpu / 1000} CPU cores,{" "} + {resources.memory} MB RAM +
+ + ) : null} +
Arguments
+
+ +
+
Environment
+
+ +
+ +
Durable
+
{lifecycle.durable ? "Yes" : "No"}
+
+
+
+ ) : null} + + } + > + + + + ); +} diff --git a/frontend/src/components/actors/actor-state-change-indicator.tsx b/frontend/src/components/actors/actor-state-change-indicator.tsx new file mode 100644 index 0000000000..c02072c6fc --- /dev/null +++ b/frontend/src/components/actors/actor-state-change-indicator.tsx @@ -0,0 +1,45 @@ +import equal from "fast-deep-equal"; +import { useEffect, useRef } from "react"; +import { Badge } from "@/components"; + +function usePreviousState(state: T) { + const ref = useRef(state); + useEffect(() => { + ref.current = state; + }, [state]); + return ref.current; +} + +interface ActorStateChangeIndicatorProps { + state: unknown | undefined; +} + +export function ActorStateChangeIndicator({ + state, +}: ActorStateChangeIndicatorProps) { + const oldState = usePreviousState(state); + const hasChanged = !equal(state, oldState); + + const ref = useRef(null); + + // biome-ignore lint/correctness/useExhaustiveDependencies: its okay, we only want to run this when state changes + useEffect(() => { + if (hasChanged && ref.current) { + ref.current?.animate( + [{ opacity: 1 }, { opacity: 1, offset: 0.7 }, { opacity: 0 }], + { + duration: 500, + easing: "ease-in", + }, + ); + } + }, [state, hasChanged]); + + return ( + +
+ State changed +
+
+ ); +} diff --git a/frontend/src/components/actors/actor-state-tab.tsx b/frontend/src/components/actors/actor-state-tab.tsx new file mode 100644 index 0000000000..af3ce20cff --- /dev/null +++ b/frontend/src/components/actors/actor-state-tab.tsx @@ -0,0 +1,76 @@ +import { useQuery } from "@tanstack/react-query"; +import type { PropsWithChildren } from "react"; +import { DocsSheet } from "../docs-sheet"; +import { Button } from "../ui/button"; +import { ActorEditableState } from "./actor-editable-state"; +import { useActor } from "./actor-queries-context"; +import { useActorsView } from "./actors-view-context-provider"; +import { useManager } from "./manager-context"; +import type { ActorId } from "./queries"; + +interface ActorStateTabProps { + actorId: ActorId; +} + +export function ActorStateTab({ actorId }: ActorStateTabProps) { + const { data: destroyedAt } = useQuery( + useManager().actorDestroyedAtQueryOptions(actorId), + ); + + const { links } = useActorsView(); + + const actorQueries = useActor(); + const { + data: state, + isError, + isLoading, + } = useQuery( + actorQueries.actorStateQueryOptions(actorId, { enabled: !destroyedAt }), + ); + + if (destroyedAt) { + return State Preview is unavailable for inactive Actors.; + } + + if (isError) { + return ( + + State Preview is currently unavailable. +
+ See console/logs for more details. +
+ ); + } + + if (isLoading) { + return Loading state...; + } + + if (!state?.enabled) { + return ( + +

+ State Preview is not enabled for this Actor.
You can + enable it by providing a valid state constructor. +

+ + + +
+ ); + } + + return ( +
+ +
+ ); +} + +export function Info({ children }: PropsWithChildren) { + return ( +
+ {children} +
+ ); +} diff --git a/frontend/src/components/actors/actor-status-indicator.tsx b/frontend/src/components/actors/actor-status-indicator.tsx new file mode 100644 index 0000000000..a2b1d26683 --- /dev/null +++ b/frontend/src/components/actors/actor-status-indicator.tsx @@ -0,0 +1,63 @@ +import { faMoon, Icon } from "@rivet-gg/icons"; +import { useQuery } from "@tanstack/react-query"; +import type { ComponentPropsWithRef } from "react"; +import { cn, Ping } from "@/components"; +import { useManager } from "./manager-context"; +import type { ActorId, ActorStatus } from "./queries"; + +export const QueriedActorStatusIndicator = ({ + actorId, + ...props +}: { + actorId: ActorId; +} & ComponentPropsWithRef<"span">) => { + const { data: status, isError } = useQuery( + useManager().actorStatusQueryOptions(actorId), + ); + + return ( + + ); +}; + +interface ActorStatusIndicatorProps extends ComponentPropsWithRef<"span"> { + status: ActorStatus | undefined; +} + +export const ActorStatusIndicator = ({ + status, + ...props +}: ActorStatusIndicatorProps) => { + if (status === "sleeping") { + return ; + } + + if (status === "running") { + return ( + + ); + } + + return ( + + ); +}; diff --git a/frontend/src/components/actors/actor-status-label.tsx b/frontend/src/components/actors/actor-status-label.tsx new file mode 100644 index 0000000000..ff11c3fbe7 --- /dev/null +++ b/frontend/src/components/actors/actor-status-label.tsx @@ -0,0 +1,23 @@ +import { useQuery } from "@tanstack/react-query"; +import { useManager } from "./manager-context"; +import type { ActorId, ActorStatus } from "./queries"; + +export const ACTOR_STATUS_LABEL_MAP = { + unknown: "Unknown", + starting: "Starting", + running: "Running", + stopped: "Stopped", + crashed: "Crashed", + sleeping: "Sleeping", +} satisfies Record; + +export const ActorStatusLabel = ({ status }: { status?: ActorStatus }) => { + return {status ? ACTOR_STATUS_LABEL_MAP[status] : "Unknown"}; +}; + +export const QueriedActorStatusLabel = ({ actorId }: { actorId: ActorId }) => { + const { data: status, isError } = useQuery( + useManager().actorStatusQueryOptions(actorId), + ); + return ; +}; diff --git a/frontend/src/components/actors/actor-status.tsx b/frontend/src/components/actors/actor-status.tsx new file mode 100644 index 0000000000..1b70addec9 --- /dev/null +++ b/frontend/src/components/actors/actor-status.tsx @@ -0,0 +1,52 @@ +import { cn } from "@/components"; +import { + ActorStatusIndicator, + QueriedActorStatusIndicator, +} from "./actor-status-indicator"; +import { + ActorStatusLabel, + QueriedActorStatusLabel, +} from "./actor-status-label"; +import type { ActorId, ActorStatus as ActorStatusType } from "./queries"; + +interface ActorStatusProps { + className?: string; + actorId: ActorId; +} + +export const QueriedActorStatus = ({ + className, + ...props +}: ActorStatusProps) => { + return ( +
+ + +
+ ); +}; + +export const ActorStatus = ({ + className, + status, +}: { + className?: string; + status: ActorStatusType; +}) => { + return ( +
+ + +
+ ); +}; diff --git a/frontend/src/components/actors/actor-stop-button.tsx b/frontend/src/components/actors/actor-stop-button.tsx new file mode 100644 index 0000000000..42cf628658 --- /dev/null +++ b/frontend/src/components/actors/actor-stop-button.tsx @@ -0,0 +1,69 @@ +import { faXmark, Icon } from "@rivet-gg/icons"; +import { useMutation, useQuery } from "@tanstack/react-query"; +import { useEffect, useState } from "react"; +import { Button, WithTooltip } from "@/components"; +import { useManager } from "./manager-context"; +import type { ActorId } from "./queries"; + +interface ActorStopButtonProps { + actorId: ActorId; +} + +export function ActorStopButton({ actorId }: ActorStopButtonProps) { + const { data: destroyedAt } = useQuery( + useManager().actorDestroyedAtQueryOptions(actorId), + ); + + const { mutate, isPending } = useMutation( + useManager().actorDestroyMutationOptions(actorId), + ); + + const { canDeleteActors } = useManager().features; + const [isConfirming, setIsConfirming] = useState(false); + + useEffect(() => { + if (isConfirming) { + const timer = setTimeout(() => { + setIsConfirming(false); + }, 4000); + + return () => clearTimeout(timer); + } + }, [isConfirming]); + + if (!canDeleteActors) { + return null; + } + + if (destroyedAt) { + return null; + } + + return ( + { + e?.stopPropagation(); + if (e?.shiftKey || isConfirming) { + mutate(); + return; + } + + setIsConfirming(true); + }} + > + {isConfirming && !isPending ? ( + "Are you sure?" + ) : ( + + )} + + } + content="Stop Actor" + /> + ); +} diff --git a/frontend/src/components/actors/actor-tags-select.tsx b/frontend/src/components/actors/actor-tags-select.tsx new file mode 100644 index 0000000000..b54c3cca0c --- /dev/null +++ b/frontend/src/components/actors/actor-tags-select.tsx @@ -0,0 +1,107 @@ +import { useAtomValue } from "jotai"; +import { useMemo } from "react"; +import { Combobox } from "@/components"; +import { actorTagsAtom } from "./actor-context"; +import { ActorTag } from "./actor-tags"; + +interface ActorTagsSelectProps { + value: Record; + onValueChange: (value: Record) => void; + showSelectedOptions?: number; +} + +export function ActorTagsSelect({ + value, + onValueChange, + showSelectedOptions, +}: ActorTagsSelectProps) { + const data = useAtomValue(actorTagsAtom); + + const valArray = useMemo(() => Object.entries(value), [value]); + const tags = useMemo(() => { + // upsert custom tags to the list of tags + const tags = [...data]; + for (const [key, value] of valArray) { + const found = data.find( + (tag) => tag.key === key && tag.value === value, + ); + + if (!found) { + tags.push({ key, value }); + } + } + return tags; + }, [valArray, data]); + + const val = useMemo( + () => + valArray.map(([key, value]) => { + return [key, value].join("="); + }), + [valArray], + ); + + const options = useMemo( + () => + tags.map((tag) => { + return { + label: ( + + + {tag.key}={tag.value} + + + ), + value: [tag.key, tag.value].join("="), + tag, + }; + }), + [tags], + ); + + const handleValueChange = (value: string[]) => { + onValueChange( + Object.fromEntries( + value.map((v) => { + // its safe to split by "=" because the value is a tag + const [key, value] = v.split("="); + return [key.trim(), value.trim()]; + }), + ), + ); + }; + + const handleCreateOption = (option: string) => { + const parts = option.split("="); + if (parts.length !== 2) return; + + const [key, value] = parts.map((part) => part.trim()); + if (!key || !value) return; + + onValueChange(Object.fromEntries([...valArray, [key, value]])); + }; + + return ( + { + const tagKey = option.tag.key.toLowerCase(); + const tagValue = option.tag.value.toLowerCase(); + + if (search.includes("=")) { + const [key, value] = search.split("="); + return tagKey.includes(key) && tagValue.includes(value); + } + return tagKey.includes(search) || tagValue.includes(search); + }} + className="w-full min-w-[20rem]" + /> + ); +} diff --git a/frontend/src/components/actors/actor-tags.tsx b/frontend/src/components/actors/actor-tags.tsx new file mode 100644 index 0000000000..95e1a60bf1 --- /dev/null +++ b/frontend/src/components/actors/actor-tags.tsx @@ -0,0 +1,141 @@ +import { faTag, Icon } from "@rivet-gg/icons"; +import { forwardRef, type ReactNode, useState } from "react"; +import { + Button, + cn, + DiscreteCopyButton, + Slot, + Slottable, + WithTooltip, +} from "@/components"; + +const BUILT_IN_TAGS = { + actors: ["framework", "framework-version"], + builds: ["current"], +}; + +export const ACTOR_FRAMEWORK_TAG_VALUE = "rivetkit"; + +export const ActorTag = forwardRef< + HTMLSpanElement, + { children: ReactNode; className?: string } +>(({ children, className, ...props }, ref) => ( + + + {children} + +)); + +interface ActorTagsProps { + tags?: unknown; + excludeBuiltIn?: keyof typeof BUILT_IN_TAGS; + className?: string; + truncate?: boolean; + copy?: boolean; + max?: number; + hoverable?: boolean; +} + +export function ActorTags({ + tags = {}, + excludeBuiltIn = undefined, + truncate = true, + className, + hoverable = true, + max = Number.POSITIVE_INFINITY, + copy = true, +}: ActorTagsProps) { + const withoutBuiltIn = Object.entries(tags ?? {}).filter(([key]) => + excludeBuiltIn ? !BUILT_IN_TAGS[excludeBuiltIn].includes(key) : true, + ); + + const [isTruncatedList, setTruncatedList] = useState( + withoutBuiltIn.length > max, + ); + + const truncated = withoutBuiltIn.filter((_, index) => + isTruncatedList ? index < max : true, + ); + + const truncatedCount = withoutBuiltIn.length - truncated.length; + + return ( +
+ {truncated.length > 0 ? ( + <> + {truncated + .sort(([a], [b]) => a.localeCompare(b)) + .map(([key, value]) => { + let trigger = truncate ? ( + + + {key}={value} + + + ) : ( + + + {key}={value} + + + ); + + trigger = copy ? ( + + + {trigger} + + + ) : ( + trigger + ); + + return truncate && hoverable && !copy ? ( + + ) : ( + trigger + ); + })} + + {truncatedCount > 0 ? ( + + ) : null} + + ) : null} +
+ ); +} diff --git a/frontend/src/components/actors/actors-actor-details.tsx b/frontend/src/components/actors/actors-actor-details.tsx new file mode 100644 index 0000000000..ef84c444db --- /dev/null +++ b/frontend/src/components/actors/actors-actor-details.tsx @@ -0,0 +1,368 @@ +import { faQuestionSquare, Icon } from "@rivet-gg/icons"; +import { + useQuery, + useSuspenseInfiniteQuery, + useSuspenseQuery, +} from "@tanstack/react-query"; +import { useMatch } from "@tanstack/react-router"; +import { memo, type ReactNode, Suspense, useMemo } from "react"; +import { useInspectorCredentials } from "@/app/credentials-context"; +import { + cn, + Flex, + Tabs, + TabsContent, + TabsList, + TabsTrigger, +} from "@/components"; +import { createEngineActorContext } from "@/queries/actor-engine"; +import { createInspectorActorContext } from "@/queries/actor-inspector"; +import { + type NamespaceNameId, + runnersQueryOptions, +} from "@/queries/manager-engine"; +import { ActorConfigTab } from "./actor-config-tab"; +import { ActorConnectionsTab } from "./actor-connections-tab"; +import { ActorDatabaseTab } from "./actor-db-tab"; +import { ActorDetailsSettingsProvider } from "./actor-details-settings"; +import { ActorEventsTab } from "./actor-events-tab"; +import { ActorLogsTab } from "./actor-logs-tab"; +import { ActorMetricsTab } from "./actor-metrics-tab"; +import { ActorProvider } from "./actor-queries-context"; +import { ActorStateTab } from "./actor-state-tab"; +import { QueriedActorStatus } from "./actor-status"; +import { ActorStopButton } from "./actor-stop-button"; +import { ActorsSidebarToggleButton } from "./actors-sidebar-toggle-button"; +import { useActorsView } from "./actors-view-context-provider"; +import { ActorConsole } from "./console/actor-console"; +import { useManager } from "./manager-context"; +import { ActorFeature, type ActorId } from "./queries"; +import { ActorWorkerContextProvider } from "./worker/actor-worker-context"; + +interface ActorsActorDetailsProps { + tab?: string; + actorId: ActorId; + onTabChange?: (tab: string) => void; + onExportLogs?: ( + actorId: string, + typeFilter?: string, + filter?: string, + ) => Promise; + isExportingLogs?: boolean; +} + +export const ActorsActorDetails = memo( + ({ tab, onTabChange, actorId }: ActorsActorDetailsProps) => { + const { data: features = [] } = useQuery( + useManager().actorFeaturesQueryOptions(actorId), + ); + + const supportsConsole = features?.includes(ActorFeature.Console); + + return ( + + + +
+ + + {supportsConsole ? ( + + ) : null} +
+
+
+
+ ); + }, +); + +export const ActorsActorEmptyDetails = ({ + features, +}: { + features: ActorFeature[]; +}) => { + const { copy } = useActorsView(); + return ( +
+ +
+ +

{copy.selectActor}

+
+
+
+ ); +}; + +export function ActorTabs({ + tab, + features, + onTabChange, + actorId, + className, + disabled, + children, +}: { + disabled?: boolean; + tab?: string; + features: ActorFeature[]; + onTabChange?: (tab: string) => void; + actorId?: ActorId; + className?: string; + children?: ReactNode; +}) { + const supportsState = features?.includes(ActorFeature.State); + const supportsLogs = features?.includes(ActorFeature.Logs); + const supportsConnections = features?.includes(ActorFeature.Connections); + const supportsMetadata = features?.includes(ActorFeature.Config); + const supportsMetrics = features?.includes(ActorFeature.Metrics); + const supportsEvents = features?.includes(ActorFeature.EventsMonitoring); + const supportsDatabase = features?.includes(ActorFeature.Database); + + const defaultTab = supportsState ? "state" : "logs"; + const value = disabled ? undefined : tab || defaultTab; + + return ( + +
+ +
+ + {supportsState ? ( + + State + + ) : null} + {supportsConnections ? ( + + Connections + + ) : null} + {supportsEvents ? ( + + Events + + ) : null} + {supportsDatabase ? ( + + Database + + ) : null} + {supportsLogs ? ( + + Logs + + ) : null} + {supportsMetadata ? ( + + Metadata + + ) : null} + {supportsMetrics ? ( + + Metrics + + ) : null} + + {actorId ? ( + + + + + ) : null} +
+
+ {actorId ? ( + <> + {supportsLogs ? ( + + }> + + + + ) : null} + {supportsMetadata ? ( + + + + ) : null} + {supportsConnections ? ( + + + + ) : null} + {supportsEvents ? ( + + + + ) : null} + {supportsDatabase ? ( + + + + ) : null} + {supportsState ? ( + + + + ) : null} + {supportsMetrics ? ( + + + + ) : null} + + ) : null} + {children} +
+ ); +} + +function ActorContextProvider(props: { + actorId: ActorId; + children: ReactNode; +}) { + return __APP_TYPE__ === "inspector" ? ( + + ) : ( + + ); +} + +function ActorInspectorProvider({ + actorId, + children, +}: { + actorId: ActorId; + children: ReactNode; +}) { + const { data } = useSuspenseQuery(useManager().actorQueryOptions(actorId)); + const { credentials } = useInspectorCredentials(); + + if (!credentials?.url || !credentials?.token) { + throw new Error("Missing inspector credentials"); + } + + const actorContext = useMemo(() => { + return createInspectorActorContext({ + ...credentials, + name: data.name || "", + }); + }, [credentials, data.name]); + + return {children}; +} + +function ActorEngineProvider({ + actorId, + children, +}: { + actorId: ActorId; + children: ReactNode; +}) { + const { data: actor } = useSuspenseQuery( + useManager().actorQueryOptions(actorId), + ); + + const match = useMatch({ + from: "/_layout/ns/$namespace", + }); + + if (!match.params.namespace || !actor.runner) { + throw new Error("Actor is missing required fields"); + } + + const { data: runners } = useSuspenseInfiniteQuery( + runnersQueryOptions({ + namespace: match.params.namespace as NamespaceNameId, + }), + ); + + const runner = runners.find((runner) => runner.name === actor.runner); + + if (!runner) { + throw new Error("Runner not found"); + } + + const actorContext = useMemo(() => { + return createEngineActorContext({ + token: (runner.metadata?.inspectorToken as string) || "", + }); + }, [runner.metadata?.inspectorToken]); + return {children}; +} diff --git a/frontend/src/components/actors/actors-actor-not-found.tsx b/frontend/src/components/actors/actors-actor-not-found.tsx new file mode 100644 index 0000000000..9cf7d8f7c1 --- /dev/null +++ b/frontend/src/components/actors/actors-actor-not-found.tsx @@ -0,0 +1,33 @@ +// import { isRivetError } from "@/lib/utils"; +// import { RivetError } from "@rivet-gg/api"; +import { faCircleExclamation, Icon } from "@rivet-gg/icons"; +import type { ErrorComponentProps } from "@tanstack/react-router"; +import { ActorsSidebarToggleButton } from "./actors-sidebar-toggle-button"; + +export function ActorsActorError({ error }: ErrorComponentProps) { + // if (isRivetError(error) || error instanceof RivetError) { + // return ( + //
+ //
+ // + //
+ //
+ // + // Actor not found. + //
+ //
+ // ); + // } + + return ( +
+
+ +
+
+ + Error occurred while fetching Actor. +
+
+ ); +} diff --git a/frontend/src/components/actors/actors-builds-panel.tsx b/frontend/src/components/actors/actors-builds-panel.tsx new file mode 100644 index 0000000000..0053f05a0f --- /dev/null +++ b/frontend/src/components/actors/actors-builds-panel.tsx @@ -0,0 +1,86 @@ +import { + // @ts-expect-error + faActorsBorderless, + Icon, +} from "@rivet-gg/icons"; +import { useInfiniteQuery } from "@tanstack/react-query"; +import { useNavigate, useSearch } from "@tanstack/react-router"; +import { Fragment } from "react/jsx-runtime"; +import { Button } from "../ui/button"; +import { ScrollArea } from "../ui/scroll-area"; +import { Skeleton } from "../ui/skeleton"; +import { VisibilitySensor } from "../visibility-sensor"; +import { useFilters } from "./actor-filters-context"; +import { ACTORS_PER_PAGE, useManager } from "./manager-context"; + +export function ActorsBuildsPanel() { + const { + data, + isSuccess, + isLoading, + hasNextPage, + fetchNextPage, + isFetchingNextPage, + } = useInfiniteQuery(useManager().buildsQueryOptions()); + + const navigate = useNavigate({ from: "/ns/$namespace" }); + const search = useSearch({ from: "/_layout/ns/$namespace" }); + + const isSearchingById = useFilters( + (filters) => filters.id?.value?.length > 0, + ); + + return ( + +
+ {isSearchingById ? ( +

+ When searching by ID, the list of names is not + available. +

+ ) : null} + {data?.map((build) => ( + + ))} + {isSuccess && data.length === 0 && ( +
+ No Actor Names found. +
+ )} + {isFetchingNextPage || isLoading + ? Array(ACTORS_PER_PAGE) + .fill(null) + .map((_, i) => ( + + + + )) + : null} +
+ {hasNextPage ? : null} +
+ ); +} diff --git a/frontend/src/components/actors/actors-layout-context.tsx b/frontend/src/components/actors/actors-layout-context.tsx new file mode 100644 index 0000000000..bcc67a9e1f --- /dev/null +++ b/frontend/src/components/actors/actors-layout-context.tsx @@ -0,0 +1,42 @@ +import type { ReactNode, RefObject } from "react"; +import { createContext, useContext, useMemo } from "react"; +import { assertNonNullable } from "../lib/utils"; +import type { ImperativePanelHandle } from "../ui/resizable"; + +export interface ActorsLayoutContextValue { + detailsRef: RefObject; + isDetailsColCollapsed: boolean; +} + +export const ActorsLayoutContext = + createContext(null); + +interface ActorsLayoutProviderProps extends ActorsLayoutContextValue { + children: ReactNode; +} + +export function ActorsLayoutContextProvider({ + children, + isDetailsColCollapsed, + detailsRef, +}: ActorsLayoutProviderProps) { + return ( + ({ + detailsRef, + isDetailsColCollapsed, + }), + [detailsRef, isDetailsColCollapsed], + )} + > + {children} + + ); +} + +export function useActorsLayout() { + const context = useContext(ActorsLayoutContext); + assertNonNullable(context); + return context; +} diff --git a/frontend/src/components/actors/actors-layout.tsx b/frontend/src/components/actors/actors-layout.tsx new file mode 100644 index 0000000000..9800e2c233 --- /dev/null +++ b/frontend/src/components/actors/actors-layout.tsx @@ -0,0 +1,34 @@ +import { memo, type ReactNode, useState } from "react"; +import { cn, ls } from "../lib/utils"; +import { ActorsLayoutContextProvider } from "./actors-layout-context"; + +interface ActorsListPreviewProps { + left: ReactNode; + right: ReactNode; + className?: string; +} + +export const ActorsLayout = memo( + ({ left, right, className }: ActorsListPreviewProps) => { + const [folded, setFolded] = useState(() => ls.actorsList.getFolded()); + + return ( + +
+ {left} +
+ {right} +
+
+
+ ); + }, +); diff --git a/frontend/src/components/actors/actors-list-panel.tsx b/frontend/src/components/actors/actors-list-panel.tsx new file mode 100644 index 0000000000..aea9d29000 --- /dev/null +++ b/frontend/src/components/actors/actors-list-panel.tsx @@ -0,0 +1,5 @@ +import { ActorsList } from "./actors-list"; + +export function ActorsListPanel() { + return ; +} diff --git a/frontend/src/components/actors/actors-list-preview.tsx b/frontend/src/components/actors/actors-list-preview.tsx new file mode 100644 index 0000000000..5b7d191b4e --- /dev/null +++ b/frontend/src/components/actors/actors-list-preview.tsx @@ -0,0 +1,92 @@ +import { memo, type ReactNode, Suspense, useRef, useState } from "react"; +import { cn } from "../lib/utils"; +import { + type ImperativePanelHandle, + ResizableHandle, + ResizablePanel, + ResizablePanelGroup, +} from "../ui/resizable"; +import { ActorsLayoutContextProvider } from "./actors-layout-context"; +import { ActorsListPanel } from "./actors-list-panel"; +import { useRootLayout } from "./root-layout-context"; + +interface ActorsListPreviewProps { + children: ReactNode; + showDetails?: boolean; +} + +export const ActorsListPreview = memo( + ({ children, showDetails }: ActorsListPreviewProps) => { + const detailsColRef = useRef(null); + + const { isSidebarCollapsed } = useRootLayout(); + const [isDetailsColCollapsed, setIsDetailsColCollapsed] = + useState(false); + + return ( + + + +
+ +
+
+ + {showDetails ? ( + <> + { + if (detailsColRef.current?.isCollapsed()) { + detailsColRef.current?.expand(); + } else { + detailsColRef.current?.collapse(); + } + }} + /> + + setIsDetailsColCollapsed(true) + } + onExpand={() => setIsDetailsColCollapsed(false)} + ref={detailsColRef} + className="flex" + > +
+ {children} +
+
+ + ) : null} +
+
+ ); + }, +); diff --git a/frontend/src/components/actors/actors-list-row.tsx b/frontend/src/components/actors/actors-list-row.tsx new file mode 100644 index 0000000000..910dd06b3e --- /dev/null +++ b/frontend/src/components/actors/actors-list-row.tsx @@ -0,0 +1,161 @@ +import { useQuery } from "@tanstack/react-query"; +import { Link, useSearch } from "@tanstack/react-router"; +import { motion } from "framer-motion"; +import { memo, useState } from "react"; +import { + Button, + cn, + DiscreteCopyButton, + RelativeTime, + Skeleton, + SmallText, + WithTooltip, +} from "@/components"; +import { VisibilitySensor } from "../visibility-sensor"; +import { useActorsFilters } from "./actor-filters-context"; +import { + ActorStatusIndicator, + QueriedActorStatusIndicator, +} from "./actor-status-indicator"; +import { QueriedActorStatusLabel } from "./actor-status-label"; +import { useManager } from "./manager-context"; +import type { ActorId } from "./queries"; + +interface ActorsListRowProps { + className?: string; + actorId: ActorId; + isCurrent?: boolean; +} + +export const ActorsListRow = memo( + ({ className, actorId, isCurrent }: ActorsListRowProps) => { + const [isVisible, setIsVisible] = useState(false); + + return ( +
+ } + content={ + + } + /> +
+ + +
+ + + + ) : ( + + )} + + + + ); + }, +); + +function Id({ actorId }: { actorId: ActorId }) { + const { pick } = useActorsFilters(); + const showIds = useSearch({ + strict: false, + select: (search) => pick(search).showIds?.value?.includes("1"), + }); + + if (!showIds) { + return
; + } + + return ( + + + {actorId.includes("-") + ? actorId.split("-")[0] + : actorId.substring(0, 8)} + + + ); +} + +function Tags({ actorId }: { actorId: ActorId }) { + const { data } = useQuery(useManager().actorKeysQueryOptions(actorId)); + + return {data || "-"}; +} + +function Timestamp({ actorId }: { actorId: ActorId }) { + const { data: { createdAt, destroyedAt } = {} } = useQuery( + useManager().actorQueryOptions(actorId), + ); + + const ts = destroyedAt || createdAt; + + const timestamp = ts ? new Date(ts) : null; + + return ( + + {timestamp ? ( + } + content={timestamp.toLocaleString()} + /> + ) : ( + - + )} + + ); +} + +function SkeletonContent() { + return ( + <> +
+ +
+ +
+ +
+ + ); +} + +export function ActorsListRowSkeleton() { + return ( +
+ +
+ ); +} diff --git a/frontend/src/components/actors/actors-list.tsx b/frontend/src/components/actors/actors-list.tsx new file mode 100644 index 0000000000..ba634652f4 --- /dev/null +++ b/frontend/src/components/actors/actors-list.tsx @@ -0,0 +1,381 @@ +import { + // @ts-expect-error + faActors, + faMagnifyingGlass, + faNodeJs, + faQuestionSquare, + faReact, + faSidebar, + faSidebarFlip, + Icon, +} from "@rivet-gg/icons"; +import { + useInfiniteQuery, + useSuspenseInfiniteQuery, +} from "@tanstack/react-query"; +import { Navigate, useNavigate, useSearch } from "@tanstack/react-router"; +import { Suspense, useCallback } from "react"; +import { + Button, + DocsSheet, + FilterCreator, + FiltersDisplay, + type OnFiltersChange, + type PickFiltersOptions, + ScrollArea, + ShimmerLine, + SmallText, + WithTooltip, +} from "@/components"; +import { VisibilitySensor } from "../visibility-sensor"; +import { useActorsFilters } from "./actor-filters-context"; +import { useActorsLayout } from "./actors-layout-context"; +import { ActorsListRow, ActorsListRowSkeleton } from "./actors-list-row"; +import { useActorsView } from "./actors-view-context-provider"; +import { CreateActorButton } from "./create-actor-button"; +import { ACTORS_PER_PAGE, useManager } from "./manager-context"; +import { useRootLayout } from "./root-layout-context"; + +export function ActorsList() { + return ( + + +
+ }> + + + + +
+
+ ); +} + +function TopBar() { + const { isSidebarCollapsed, sidebarRef } = useRootLayout(); + const { isDetailsColCollapsed, detailsRef } = useActorsLayout(); + + return ( +
+ {isSidebarCollapsed ? ( + sidebarRef.current?.expand()} + variant="outline" + size="icon-sm" + > + + + } + content="Expand Actor Names column" + /> + ) : null} +
+ {__APP_TYPE__ === "hub" ? :
} +
+ + +
+
+ {isDetailsColCollapsed ? ( + detailsRef.current?.expand()} + variant="outline" + size="icon-sm" + > + + + } + content="Expand details column" + /> + ) : null} + +
+ ); +} + +function LoadingIndicator() { + const n = useSearch({ + from: "/_layout", + select: (state) => state.n, + }); + const filters = useFiltersValue({ includeEphemeral: false }); + const { isLoading } = useInfiniteQuery( + useManager().actorsListQueryOptions({ n, filters }), + ); + if (isLoading) { + return ; + } + return null; +} + +function List() { + const filters = useFiltersValue({ includeEphemeral: false }); + const { actorId, n } = useSearch({ + from: "/_layout", + }); + const { data: actorIds = [] } = useInfiniteQuery( + useManager().actorsListQueryOptions({ n, filters }), + ); + + return ( + <> + {actorIds.map((id) => ( + + ))} + + ); +} + +function ActorIdPrefiller() { + const { n, actorId } = useSearch({ + from: "/_layout", + select: (state) => ({ + n: state.n, + actorId: state.actorId, + }), + }); + const filters = useFiltersValue({ includeEphemeral: false }); + const { data } = useSuspenseInfiniteQuery( + useManager().actorsListQueryOptions({ + n, + filters, + }), + ); + + if (!actorId && data?.[0]) { + return ( + ({ ...search, actorId: data?.[0] })} + replace + /> + ); + } + + return null; +} + +function Pagination() { + const n = useSearch({ + from: "/_layout", + select: (state) => state.n, + }); + const filters = useFiltersValue({ includeEphemeral: false }); + const { hasNextPage, isFetchingNextPage, fetchNextPage, data } = + useSuspenseInfiniteQuery( + useManager().actorsListPaginationQueryOptions({ + n, + filters, + }), + ); + + if (isFetchingNextPage) { + return ; + } + + if (hasNextPage) { + return ; + } + + return ; +} + +export function ListSkeleton() { + return ( +
+ {Array(ACTORS_PER_PAGE) + .fill(null) + .map((_, i) => ( + + ))} +
+ ); +} + +function useFiltersValue(opts: PickFiltersOptions = {}) { + const { pick } = useActorsFilters(); + return useSearch({ + from: "/_layout", + select: (state) => pick(state, opts), + }); +} + +function EmptyState({ count }: { count: number }) { + const navigate = useNavigate(); + const names = useSearch({ + from: "/_layout", + select: (state) => state.n, + }); + const { copy, links } = useActorsView(); + const { remove, pick } = useActorsFilters(); + + const { data: availableNamesCount = 0 } = useInfiniteQuery( + useManager().buildsCountQueryOptions(), + ); + + const filtersCount = useSearch({ + from: "/_layout", + select: (state) => + Object.values(pick(state, { includeEphemeral: false })).length, + }); + + const clearFilters = () => { + navigate({ + to: ".", + search: (prev) => ({ + ...remove(prev), + }), + }); + }; + + return ( +
+ {(!names || names?.length === 0) && availableNamesCount > 0 ? ( +
+ +

+ No Actor Name selected. +
+ + Select an Actor Name from the list on the left. + +

+
+ ) : count === 0 ? ( + filtersCount === 0 ? ( +
+ + + {copy.noActorsFound} + +
+ {" "} + + Use one of the quick start guides to get + started. + +
+ + + + + + +
+
+
+ ) : ( + <> + + {copy.noActorsMatchFilter} + + + + ) + ) : ( + + {copy.noMoreActors} + + )} +
+ ); +} + +function useFiltersChangeCallback(): OnFiltersChange { + const navigate = useNavigate(); + const { pick, remove } = useActorsFilters(); + + return useCallback( + (fnOrValue) => { + if (typeof fnOrValue === "function") { + navigate({ + to: ".", + search: (old) => { + const filters = pick(old); + const prev = remove(old); + + return { + ...prev, + ...Object.fromEntries( + Object.entries(fnOrValue(filters)).filter( + ([, filter]) => filter.value.length > 0, + ), + ), + }; + }, + }); + } else { + navigate({ + to: ".", + search: (value) => ({ + ...remove(value), + ...Object.fromEntries( + Object.entries(fnOrValue).filter( + ([, filter]) => filter.value.length > 0, + ), + ), + }), + }); + } + }, + [navigate, pick], + ); +} + +function Filters() { + const { definitions } = useActorsFilters(); + const filters = useFiltersValue(); + const onFiltersChange = useFiltersChangeCallback(); + + return ( + } + /> + ); +} + +function Display() { + const { definitions } = useActorsFilters(); + const filters = useFiltersValue(); + const onFiltersChange = useFiltersChangeCallback(); + + return ( + + ); +} diff --git a/frontend/src/components/actors/actors-sidebar-toggle-button.tsx b/frontend/src/components/actors/actors-sidebar-toggle-button.tsx new file mode 100644 index 0000000000..24a6a75e2e --- /dev/null +++ b/frontend/src/components/actors/actors-sidebar-toggle-button.tsx @@ -0,0 +1,23 @@ +import { faSidebar, Icon } from "@rivet-gg/icons"; +import { Button } from "@/components"; +import { useActorsLayout } from "./actors-layout-context"; + +export function ActorsSidebarToggleButton() { + const { setFolded, isFolded } = useActorsLayout(); + + if (!isFolded) { + return null; + } + return ( +
+ +
+ ); +} diff --git a/frontend/src/components/actors/actors-view-context-provider.tsx b/frontend/src/components/actors/actors-view-context-provider.tsx new file mode 100644 index 0000000000..db405dde8d --- /dev/null +++ b/frontend/src/components/actors/actors-view-context-provider.tsx @@ -0,0 +1,62 @@ +import { createContext, useContext } from "react"; + +const defaultValue = { + copy: { + createActor: "Create Actor", + createActorUsingForm: "Create Actor using simple form", + noActorsFound: "No Actors found", + selectActor: ( + <> + No Actor selected. +
{" "} + + Select an Actor from the list to view its details. + + + ), + goToActor: "Go to Actor", + showActorList: "Show Actor List", + showHiddenActors: "Show hidden Actors", + actorId: "Actor ID", + noActorsMatchFilter: "No Actors match the filters.", + noMoreActors: "No more Actors to load.", + + createActorModal: { + title: (name?: string) => + name ? `Create '${name}'` : "Create Actor", + description: + "Quickly create an Actor by providing the necessary details.", + }, + + actorNotFound: "Actor not found", + actorNotFoundDescription: + "Change your filters to find the Actor you are looking for.", + + gettingStarted: { + title: "Getting Started with Actors", + description: + "Use a quick start guide to start deploying Actors to your environment.", + }, + }, + links: { + gettingStarted: { + node: "https://www.rivet.gg/docs/actors/quickstart/backend/", + react: "https://www.rivet.gg/docs/actors/quickstart/react/", + }, + state: "https://www.rivet.gg/docs/actors/state/", + }, + canCreate: true, +}; + +export const ActorsViewContext = + createContext(defaultValue); + +export const useActorsView = () => { + const context = useContext(ActorsViewContext); + if (!context) { + throw new Error( + "useActorsView must be used within a ActorsViewContextProvider", + ); + } + return context; +}; diff --git a/frontend/src/components/actors/build-select.tsx b/frontend/src/components/actors/build-select.tsx new file mode 100644 index 0000000000..ab53bd2140 --- /dev/null +++ b/frontend/src/components/actors/build-select.tsx @@ -0,0 +1,47 @@ +import { useInfiniteQuery } from "@tanstack/react-query"; +import { useMemo } from "react"; +import { Combobox } from "@/components"; +import { useManager } from "./manager-context"; + +interface BuildSelectProps { + onValueChange: (value: string) => void; + value: string; +} + +export function BuildSelect({ onValueChange, value }: BuildSelectProps) { + const { data = [] } = useInfiniteQuery(useManager().buildsQueryOptions()); + + const builds = useMemo(() => { + return data.map((build) => { + return { + label: ( +
+
+
+ {build.tags?.name || build.name} +
+ {build.createdAt ? ( +
+ Created: {build.createdAt.toLocaleString()} +
+ ) : null} +
+
+ ), + value: build.name, + build, + }; + }); + }, [data]); + + return ( + option.build.name.includes(search)} + className="w-full" + /> + ); +} diff --git a/frontend/src/components/actors/console/actor-console-input.tsx b/frontend/src/components/actors/console/actor-console-input.tsx new file mode 100644 index 0000000000..78eff3a7c7 --- /dev/null +++ b/frontend/src/components/actors/console/actor-console-input.tsx @@ -0,0 +1,70 @@ +import { useQuery } from "@tanstack/react-query"; +import { useRef } from "react"; +import { Button, ScrollArea } from "@/components"; +import { useActor } from "../actor-queries-context"; +import type { ActorId } from "../queries"; +import { useActorWorker } from "../worker/actor-worker-context"; +import { ActorConsoleMessage } from "./actor-console-message"; +import { ReplInput, type ReplInputRef, replaceCode } from "./repl-input"; + +interface ActorConsoleInputProps { + actorId: ActorId; +} + +export function ActorConsoleInput({ actorId }: ActorConsoleInputProps) { + const worker = useActorWorker(); + + const actorQueries = useActor(); + const { data: { rpcs = [] } = {} } = useQuery( + actorQueries.actorRpcsQueryOptions(actorId), + ); + + const ref = useRef(null); + + return ( +
+ + + { + worker.run(code); + }} + /> + +
+
+ {rpcs.map((rpc) => ( + + ))} +
+
+
+
+ ); +} diff --git a/frontend/src/components/actors/console/actor-console-log-formatted.tsx b/frontend/src/components/actors/console/actor-console-log-formatted.tsx new file mode 100644 index 0000000000..11545a63f5 --- /dev/null +++ b/frontend/src/components/actors/console/actor-console-log-formatted.tsx @@ -0,0 +1,27 @@ +import type { FormattedCode } from "../worker/actor-worker-schema"; + +export function ActorConsoleLogFormatted({ tokens }: FormattedCode) { + return ( + <> + {tokens.map((tokensLine, index) => ( + + {tokensLine.map((token, index) => ( + + {token.content} + + ))} + + ))} + + ); +} diff --git a/frontend/src/components/actors/console/actor-console-log.tsx b/frontend/src/components/actors/console/actor-console-log.tsx new file mode 100644 index 0000000000..38b97eb0cf --- /dev/null +++ b/frontend/src/components/actors/console/actor-console-log.tsx @@ -0,0 +1,86 @@ +import { memo } from "react"; +import type { ReplCommand } from "../worker/actor-worker-container"; +import { ActorConsoleLogFormatted } from "./actor-console-log-formatted"; +import { ActorConsoleMessage } from "./actor-console-message"; +import { ActorObjectInspector } from "./actor-inspector"; + +type ActorConsoleLogProps = ReplCommand & { + showTimestmaps: boolean; +}; + +export const ActorConsoleLog = memo((props: ActorConsoleLogProps) => { + return ( + <> + + {"formatted" in props && props.formatted ? ( + + ) : null} + + {"error" in props ? ( + + {props.error && + typeof props.error === "object" && + "toString" in props.error + ? props.error.toString() + : JSON.stringify(props.error)} + + ) : null} + {props.logs?.map((log, index) => ( + + {log.data?.map((element, key) => { + if (typeof element === "string") { + return ( + + {element} + + ); + } + return ( + + ); + })} + + ))} + {"result" in props ? ( + + {typeof props.result === "string" ? ( + props.result + ) : ( + + )} + + ) : null} + + ); +}); diff --git a/frontend/src/components/actors/console/actor-console-logs.tsx b/frontend/src/components/actors/console/actor-console-logs.tsx new file mode 100644 index 0000000000..cf4cd6dad4 --- /dev/null +++ b/frontend/src/components/actors/console/actor-console-logs.tsx @@ -0,0 +1,46 @@ +import { useLayoutEffect, useRef } from "react"; +import { ScrollArea } from "@/components"; +import { useActorDetailsSettings } from "../actor-details-settings"; +import { useActorReplCommands } from "../worker/actor-worker-context"; +import { ActorConsoleLog } from "./actor-console-log"; + +export function ActorConsoleLogs() { + const isScrolledToBottom = useRef(true); + const ref = useRef(null); + const commands = useActorReplCommands(); + + const [settings] = useActorDetailsSettings(); + + // biome-ignore lint/correctness/useExhaustiveDependencies: we want to run this effect on every commands change + useLayoutEffect(() => { + if (ref.current && isScrolledToBottom.current) { + ref.current.scrollTop = ref.current.scrollHeight; + } + }, [commands]); + + return ( + { + if (ref.current) { + isScrolledToBottom.current = + ref.current.scrollTop + ref.current.clientHeight >= + ref.current.scrollHeight - 1; + } + }, + }} + className="w-full flex-1" + > + {commands.map((log) => ( + + ))} + + ); +} diff --git a/frontend/src/components/actors/console/actor-console-message.tsx b/frontend/src/components/actors/console/actor-console-message.tsx new file mode 100644 index 0000000000..71acc39cb0 --- /dev/null +++ b/frontend/src/components/actors/console/actor-console-message.tsx @@ -0,0 +1,100 @@ +import { + faAngleLeft, + faAngleRight, + faExclamationCircle, + faSpinnerThird, + faWarning, + Icon, +} from "@rivet-gg/icons"; +import { format } from "date-fns"; +import { forwardRef, type ReactNode } from "react"; +import { cn } from "@/components"; + +interface ActorConsoleMessageProps { + variant: + | "input" + | "input-pending" + | "output" + | "error" + | "log" + | "warn" + | "info" + | "debug"; + timestamp?: Date; + className?: string; + children: ReactNode; +} + +export const ActorConsoleMessage = forwardRef< + HTMLDivElement, + ActorConsoleMessageProps +>(({ children, variant, timestamp, className, ...props }, ref) => { + return ( +
+
+ +
+
+ {timestamp + ? format(timestamp, "LLL dd HH:mm:ss").toUpperCase() + : null} +
+
+ {children} +
+
+ ); +}); + +export const ConsoleMessageVariantIcon = ({ + variant, + className, +}: { + variant: string; + className?: string; +}) => { + if (variant === "input") { + return ; + } + if (variant === "input-pending") { + return ( + + ); + } + if (variant === "output") { + return ; + } + if (variant === "error") { + return ( + + ); + } + if (variant === "warn") { + return ; + } + return ; +}; + +export const getConsoleMessageVariant = (variant: string) => + cn({ + "bg-red-950/30 border-red-800/40 text-red-400 z-10": + variant === "error", + "bg-yellow-500/10 border-yellow-800/40 text-yellow-200 z-10": + variant === "warn", + "bg-blue-950/30 border-blue-800/40 text-blue-400 z-10": + variant === "debug", + }); diff --git a/frontend/src/components/actors/console/actor-console.tsx b/frontend/src/components/actors/console/actor-console.tsx new file mode 100644 index 0000000000..4def5ac856 --- /dev/null +++ b/frontend/src/components/actors/console/actor-console.tsx @@ -0,0 +1,80 @@ +import { faChevronDown, Icon } from "@rivet-gg/icons"; +import { useQuery } from "@tanstack/react-query"; +import { AnimatePresence, motion } from "framer-motion"; +import { useState } from "react"; +import { Button, cn } from "@/components"; +import { useActor } from "../actor-queries-context"; +import { useManager } from "../manager-context"; +import type { ActorId } from "../queries"; +import { useActorWorkerStatus } from "../worker/actor-worker-context"; +import { ActorWorkerStatus } from "../worker/actor-worker-status"; +import { ActorConsoleInput } from "./actor-console-input"; +import { ActorConsoleLogs } from "./actor-console-logs"; + +interface ActorConsoleProps { + actorId: ActorId; +} + +export function ActorConsole({ actorId }: ActorConsoleProps) { + const [isOpen, setOpen] = useState(false); + + const status = useActorWorkerStatus(); + const managerQueries = useManager(); + const actorQueries = useActor(); + const { data: destroyedAt } = useQuery( + managerQueries.actorDestroyedAtQueryOptions(actorId), + ); + const { isSuccess, isError, isLoading } = useQuery( + actorQueries.actorPingQueryOptions(actorId, { + enabled: true, + refetchInterval: false, + }), + ); + + const isBlocked = status.type !== "ready" || !isSuccess || !!destroyedAt; + + const combinedStatus = isError + ? "error" + : isLoading + ? "pending" + : status.type; + + return ( + + + + {isOpen && !isBlocked ? ( + + + + + ) : null} + + + ); +} diff --git a/frontend/src/components/actors/console/actor-inspector.tsx b/frontend/src/components/actors/console/actor-inspector.tsx new file mode 100644 index 0000000000..195aa820c4 --- /dev/null +++ b/frontend/src/components/actors/console/actor-inspector.tsx @@ -0,0 +1,30 @@ +import type { ComponentProps } from "react"; +import { chromeDark, Inspector, type ObjectInspector } from "react-inspector"; +import { cn } from "@/components"; + +const INSPECTOR_THEME = { + ...chromeDark, + BASE_BACKGROUND_COLOR: "transparent", +}; + +export function ActorObjectInspector( + props: ComponentProps, +) { + return ( +
+ +
+ ); +} diff --git a/frontend/src/components/actors/console/repl-input.tsx b/frontend/src/components/actors/console/repl-input.tsx new file mode 100644 index 0000000000..99339d0b51 --- /dev/null +++ b/frontend/src/components/actors/console/repl-input.tsx @@ -0,0 +1,101 @@ +import { forwardRef } from "react"; +import { + CodeMirror, + type CodeMirrorRef, + type CompletionContext, + defaultKeymap, + EditorView, + External, + javascript, + javascriptLanguage, + keymap, +} from "@/components/code-mirror"; + +export const replaceCode = (editor: EditorView, code: string) => { + return editor.dispatch({ + changes: { + from: 0, + to: editor.state.doc.length, + insert: code, + }, + selection: { anchor: code.length }, + scrollIntoView: true, + annotations: [External.of(true)], + }); +}; + +const deleteBgTheme = EditorView.theme({ + ".cm-content": { padding: 0 }, +}); + +export type ReplInputRef = CodeMirrorRef; + +interface ReplInputProps { + className: string; + rpcs: string[]; + onRun: (code: string) => void; +} + +export const ReplInput = forwardRef( + ({ rpcs, onRun, className }, ref) => { + const rivetKeymap = keymap.of([ + { + key: "Enter", + run: (editor) => { + onRun(editor?.state.doc.toString()); + editor.dispatch({ + changes: { + from: 0, + to: editor.state.doc.length, + insert: "", + }, + annotations: [External.of(true)], + }); + return true; + }, + }, + ...defaultKeymap, + ]); + + const replAutocomplete = javascriptLanguage.data.of({ + autocomplete: (context: CompletionContext) => { + const word = context.matchBefore(/^actor\.\w*/); + if (!word || (word?.from === word?.to && !context.explicit)) + return null; + return { + from: word.from, + to: word.to, + boost: 99, + options: rpcs.map((rpc) => ({ + label: `actor.${rpc}(/* args */)`, + apply: `actor.${rpc}(`, + validFor: /^actor\.\w*$/, + info: `Call "${rpc}" RPC on Actor`, + })), + }; + }, + }); + + return ( + + ); + }, +); diff --git a/frontend/src/components/actors/crash-policy-select.tsx b/frontend/src/components/actors/crash-policy-select.tsx new file mode 100644 index 0000000000..b6dcc1b0e4 --- /dev/null +++ b/frontend/src/components/actors/crash-policy-select.tsx @@ -0,0 +1,27 @@ +import { Combobox } from "@/components"; +import { CrashPolicy } from "./queries"; + +const VALUES = Array.from(Object.entries(CrashPolicy)).map(([key, value]) => ({ + label: key, + value, +})); + +interface CrashPolicySelectProps { + onValueChange: (value: string) => void; + value: string; +} + +export function CrashPolicySelect({ + onValueChange, + value, +}: CrashPolicySelectProps) { + return ( + + ); +} diff --git a/frontend/src/components/actors/create-actor-button.tsx b/frontend/src/components/actors/create-actor-button.tsx new file mode 100644 index 0000000000..253e445483 --- /dev/null +++ b/frontend/src/components/actors/create-actor-button.tsx @@ -0,0 +1,59 @@ +import { faPlus, Icon } from "@rivet-gg/icons"; +import { useInfiniteQuery } from "@tanstack/react-query"; +import { useNavigate } from "@tanstack/react-router"; +import { Button, type ButtonProps, WithTooltip } from "@/components"; +import { useActorsView } from "./actors-view-context-provider"; +import { useManager } from "./manager-context"; + +export function CreateActorButton(props: ButtonProps) { + const navigate = useNavigate(); + + const manager = useManager(); + const { data } = useInfiniteQuery(useManager().buildsQueryOptions()); + + const { copy } = useActorsView(); + + const canCreate = data && data.length > 0; + + if (!manager.features.canCreateActors) { + return null; + } + + const content = ( +
+ +
+ ); + + if (canCreate) { + return content; + } + + return ( + + ); +} diff --git a/frontend/apps/hub/src/domains/project/components/current-environment-version-title.tsx b/frontend/src/components/actors/current-environment-version-title.tsx similarity index 100% rename from frontend/apps/hub/src/domains/project/components/current-environment-version-title.tsx rename to frontend/src/components/actors/current-environment-version-title.tsx diff --git a/frontend/src/components/actors/database/database-table.tsx b/frontend/src/components/actors/database/database-table.tsx new file mode 100644 index 0000000000..dfe55f4edd --- /dev/null +++ b/frontend/src/components/actors/database/database-table.tsx @@ -0,0 +1,328 @@ +import { + faAnglesUpDown, + faArrowDownWideShort, + faArrowUpWideShort, + faLink, + Icon, +} from "@rivet-gg/icons"; +import type { Column, Columns, ForeignKeys } from "@rivetkit/core/inspector"; +import { + createColumnHelper, + // SortingState, + type ExpandedState, + flexRender, + getCoreRowModel, + getExpandedRowModel, + getSortedRowModel, + type RowSelectionState, + type SortingState, + useReactTable as useTable, +} from "@tanstack/react-table"; +import { Fragment, useMemo, useState } from "react"; +import { + Badge, + Button, + Checkbox, + cn, + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components"; + +interface DatabaseTableProps { + columns: any[]; + data: any[]; + references?: ForeignKeys; + className?: string; + + enableRowSelection?: boolean; + enableSorting?: boolean; + enableCellExpanding?: boolean; + enableColumnResizing?: boolean; +} + +export function DatabaseTable({ + columns: dbCols, + data, + references, + className, + + enableRowSelection = true, + enableSorting = true, + enableCellExpanding = true, + enableColumnResizing = true, +}: DatabaseTableProps) { + const columns = useMemo(() => { + return createColumns(dbCols, references, { enableRowSelection }); + }, [dbCols, references, enableRowSelection]); + + const [rowSelection, setRowSelection] = useState({}); + const [sorting, setSorting] = useState([]); + const [expanded, setExpanded] = useState({}); + + const table = useTable({ + columns, + data, + enableRowSelection, + enableSorting, + enableCellExpanding, + enableColumnResizing, + getCoreRowModel: getCoreRowModel(), + getExpandedRowModel: getExpandedRowModel(), + getSortedRowModel: getSortedRowModel(), + defaultColumn: {}, + columnResizeMode: "onChange", + onSortingChange: setSorting, + onRowSelectionChange: setRowSelection, + paginateExpandedRows: false, + state: { + sorting, + rowSelection, + expanded, + }, + }); + + function calculateColumnSizes() { + const headers = table.getFlatHeaders(); + const colSizes: { [key: string]: number } = {}; + for (let i = 0; i < headers.length; i++) { + const header = headers[i]!; + colSizes[`--header-${header.id}-size`] = header.getSize(); + colSizes[`--col-${header.column.id}-size`] = + header.column.getSize(); + } + return colSizes; + } + + const columnSizeVars = useMemo(() => { + return calculateColumnSizes(); + }, [table.getState().columnSizingInfo, table.getState().columnSizing]); + + return ( + + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => { + return ( + + {header.isPlaceholder ? null : header.column.getCanSort() ? ( + + ) : ( +
+ {flexRender( + header.column.columnDef.header, + header.getContext(), + )} +
+ )} + {header.column.getCanResize() ? ( +
+
+
+ ) : null} + + ); + })} + + ))} + + + {table.getRowModel().rows.map((row) => ( + + + {row.getVisibleCells().map((cell) => ( + +
+
+ {flexRender( + cell.column.columnDef.cell, + cell.getContext(), + )} +
+
+
+ ))} +
+
+ ))} +
+
+ ); +} + +const ch = createColumnHelper(); + +function createColumns( + columns: Columns, + references?: ForeignKeys, + { enableRowSelection }: { enableRowSelection?: boolean } = {}, +) { + return [ + ...[ + enableRowSelection + ? ch.display({ + id: "select", + enableResizing: false, + header: ({ table }) => ( + { + if (value === "indeterminate") { + table.toggleAllRowsSelected(true); + return; + } + table.toggleAllRowsSelected(value); + }} + aria-label="Select all" + /> + ), + cell: ({ row }) => ( + { + if (value === "indeterminate") { + row.toggleSelected(true); + return; + } + row.toggleSelected(); + }} + /> + ), + }) + : null, + ].filter(Boolean), + ...columns.map((col) => + ch.accessor(col.name, { + header: (info) => ( + + {col.name}{" "} + + {col.type} + + + + ), + cell: (info) => { + if (col.type === "blob") { + return ( + + BINARY{" "} + + ); + } + const value = info.getValue(); + if (value === null) { + return ( + + NULL + + ); + } + + if (col) return <>{info.getValue()}; + }, + meta: { + type: col.type, + notNull: col.notnull, + default: col.dflt_value, + }, + }), + ), + ]; +} + +function ForeignKey({ + references, + column, +}: { + references?: ForeignKeys; + column: Column; +}) { + const ref = references?.find((ref) => ref.from === column.name); + if (!ref) return null; + return ( + + + {ref.table}.{ref.to} + + ); +} diff --git a/frontend/src/components/actors/dialogs/create-actor-dialog.tsx b/frontend/src/components/actors/dialogs/create-actor-dialog.tsx new file mode 100644 index 0000000000..535b2f97a1 --- /dev/null +++ b/frontend/src/components/actors/dialogs/create-actor-dialog.tsx @@ -0,0 +1,98 @@ +import { useMutation } from "@tanstack/react-query"; +import { useSearch } from "@tanstack/react-router"; +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from "@/components/ui/accordion"; +import type { NamespaceNameId } from "@/queries/manager-engine"; +import { + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "../../ui/dialog"; +import { Flex } from "../../ui/flex"; +import { useActorsView } from "../actors-view-context-provider"; +import * as ActorCreateForm from "../form/actor-create-form"; +import type { DialogContentProps } from "../hooks"; +import { useManager } from "../manager-context"; +import { CrashPolicy } from "../queries"; + +interface ContentProps extends DialogContentProps { + namespace: NamespaceNameId; +} + +export default function CreateActorDialog({ + onClose, + namespace, +}: ContentProps) { + const { mutateAsync } = useMutation( + useManager().createActorMutationOptions(), + ); + const name = useSearch({ + from: "/_layout", + select: (state) => state.n?.[0], + }); + + const { copy } = useActorsView(); + + return ( + { + await mutateAsync({ + name: values.name, + input: values.input ? JSON.parse(values.input) : undefined, + key: values.key, + crashPolicy: values.crashPolicy, + runnerNameSelector: values.runnerNameSelector, + }); + onClose?.(); + }} + defaultValues={{ + name, + crashPolicy: CrashPolicy.Destroy, + region: "auto", + }} + > + + {copy.createActorModal.title(name)} + + {copy.createActorModal.description} + + + + {!name ? : null} + + + {__APP_TYPE__ === "engine" ? ( + + ) : null} + + + + Advanced + + {__APP_TYPE__ === "engine" ? ( + <> + + + + + ) : null} + + + + + + + + Create + + + + ); +} diff --git a/frontend/src/components/actors/dialogs/go-to-actor-dialog.tsx b/frontend/src/components/actors/dialogs/go-to-actor-dialog.tsx new file mode 100644 index 0000000000..3baf32d185 --- /dev/null +++ b/frontend/src/components/actors/dialogs/go-to-actor-dialog.tsx @@ -0,0 +1,35 @@ +import { Button } from "../../ui/button"; +import { DialogFooter, DialogHeader, DialogTitle } from "../../ui/dialog"; +import { useActorsView } from "../actors-view-context-provider"; +import * as GoToActorForm from "../form/go-to-actor-form"; +import type { DialogContentProps } from "../hooks"; + +interface ContentProps extends DialogContentProps { + onSubmit?: (actorId: string) => void; +} + +export default function GoToActorDialogContent({ + onClose, + onSubmit, +}: ContentProps) { + const { copy } = useActorsView(); + return ( + { + onSubmit?.(actorId); + }} + > + + {copy.goToActor} + + + + + Go + + + ); +} diff --git a/frontend/apps/hub/src/domains/project/components/dynamic-servers-feature-card.tsx b/frontend/src/components/actors/dynamic-servers-feature-card.tsx similarity index 95% rename from frontend/apps/hub/src/domains/project/components/dynamic-servers-feature-card.tsx rename to frontend/src/components/actors/dynamic-servers-feature-card.tsx index 7df263034b..a021d59242 100644 --- a/frontend/apps/hub/src/domains/project/components/dynamic-servers-feature-card.tsx +++ b/frontend/src/components/actors/dynamic-servers-feature-card.tsx @@ -1,3 +1,4 @@ +import { Link as RouterLink } from "@tanstack/react-router"; import { Card, CardContent, @@ -5,8 +6,7 @@ import { CardTitle, Link, Text, -} from "@rivet-gg/components"; -import { Link as RouterLink } from "@tanstack/react-router"; +} from "@/components"; export function DynamicServersFeatureCard() { return ( diff --git a/frontend/apps/hub/src/domains/project/components/environment-select.tsx b/frontend/src/components/actors/environment-select.tsx similarity index 95% rename from frontend/apps/hub/src/domains/project/components/environment-select.tsx rename to frontend/src/components/actors/environment-select.tsx index 2261946dbc..46d5a1d141 100644 --- a/frontend/apps/hub/src/domains/project/components/environment-select.tsx +++ b/frontend/src/components/actors/environment-select.tsx @@ -1,4 +1,6 @@ -import { projectEnvironmentsQueryOptions } from "@/domains/project/queries"; +import { faCirclePlus, Icon } from "@rivet-gg/icons"; +import { useSuspenseQuery } from "@tanstack/react-query"; +import { type ComponentProps, useCallback } from "react"; import { Flex, Select, @@ -7,10 +9,8 @@ import { SelectSeparator, SelectTrigger, SelectValue, -} from "@rivet-gg/components"; -import { Icon, faCirclePlus } from "@rivet-gg/icons"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { type ComponentProps, useCallback } from "react"; +} from "@/components"; +import { projectEnvironmentsQueryOptions } from "@/domains/project/queries"; interface EnvironmentSelectProps extends ComponentProps { projectId: string; diff --git a/frontend/apps/hub/src/domains/project/components/environment-version-title.tsx b/frontend/src/components/actors/environment-version-title.tsx similarity index 85% rename from frontend/apps/hub/src/domains/project/components/environment-version-title.tsx rename to frontend/src/components/actors/environment-version-title.tsx index 0777d81cda..81aec17a58 100644 --- a/frontend/apps/hub/src/domains/project/components/environment-version-title.tsx +++ b/frontend/src/components/actors/environment-version-title.tsx @@ -1,4 +1,4 @@ -import { Badge, Flex } from "@rivet-gg/components"; +import { Badge, Flex } from "@/components"; interface EnvironmentVersionTitleProps { environment: string; diff --git a/frontend/src/components/actors/form/actor-create-form.tsx b/frontend/src/components/actors/form/actor-create-form.tsx new file mode 100644 index 0000000000..5bc179362a --- /dev/null +++ b/frontend/src/components/actors/form/actor-create-form.tsx @@ -0,0 +1,328 @@ +import { useInfiniteQuery } from "@tanstack/react-query"; +import { useEffect, useRef } from "react"; +import { type UseFormReturn, useFormContext } from "react-hook-form"; +import z from "zod"; +import { CodePreview, Input, Label } from "@/components"; +import { + type NamespaceNameId, + runnerNamesQueryOptions, +} from "@/queries/manager-engine"; +import { JsonCode } from "../../code-mirror"; +import { createSchemaForm } from "../../lib/create-schema-form"; +import { + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "../../ui/form"; +import { BuildSelect } from "../build-select"; +import { CrashPolicySelect } from "../crash-policy-select"; +import { CrashPolicy as CrashPolicyEnum } from "../queries"; +import { RegionSelect } from "../region-select"; +import { RunnerSelect } from "../runner-select"; + +const jsonValid = z.custom( + (value) => { + if (value.trim() === "") return true; + try { + JSON.parse(value); + return true; + } catch { + return false; + } + }, + { fatal: true, message: "Must be valid JSON" }, +); + +export const formSchema = z + .object({ + name: z.string().nonempty("Build is required"), + // regionId: z.string(), + key: z.string(), + input: jsonValid.optional(), + // tags: tagsFormSchema.shape.tags, + }) + .and( + __APP_TYPE__ === "engine" + ? z.object({ + region: z.string(), + runnerNameSelector: z.string(), + crashPolicy: z.nativeEnum(CrashPolicyEnum), + }) + : z.object({}), + ); + +export type FormValues = z.infer; +export type SubmitHandler = ( + values: FormValues, + form: UseFormReturn, +) => Promise; + +const { Form, Submit } = createSchemaForm(formSchema); +export { Form, Submit }; + +export const Build = () => { + const { control } = useFormContext(); + return ( + ( + + Name + + + + + Used to differentiate between different actor types. + + + + )} + /> + ); +}; + +export const CrashPolicy = () => { + const { control } = useFormContext(); + + return ( + ( + + Crash Policy + + + + + Determines the behavior of the actor on crash. + + + + )} + /> + ); +}; + +export const Keys = () => { + const { control } = useFormContext(); + return ( + ( + + Key + + + + Identifier for the Actor. + + + )} + /> + ); +}; + +export const JsonInput = () => { + const { control } = useFormContext(); + return ( + ( + + Input + + + + + Optional JSON object that will be passed to the Actor as + input. + + + + )} + /> + ); +}; + +export const RunnerNameSelector = ({ + namespace, +}: { + namespace: NamespaceNameId; +}) => { + const { control } = useFormContext(); + + return ( + ( + + Runner + + + + + Runner name selector for the actor. This is used to + select which runner the actor will run on. + + + + )} + /> + ); +}; + +export const ActorPreview = () => { + const { watch } = useFormContext(); + + const [name, key] = watch(["name", "key"]); + + return ( +
+ +
+ +
+

+ You can use above code snippet to get or create the actor in + your application. For more information, see the{" "} + + documentation + + . +

+
+ ); +}; + +export const PrefillRunnerName = ({ + namespace, +}: { + namespace: NamespaceNameId; +}) => { + const prefilled = useRef(false); + const { watch } = useFormContext(); + + const { data = [], isSuccess } = useInfiniteQuery( + runnerNamesQueryOptions({ namespace }), + ); + + const watchedValue = watch("runnerNameSelector"); + + const { setValue } = useFormContext(); + + useEffect(() => { + if ( + data.length > 0 && + isSuccess && + !watchedValue && + !prefilled.current + ) { + setValue("runnerNameSelector", data[0]); + prefilled.current = true; + } + }, [data, setValue, isSuccess, watchedValue]); + + return null; +}; + +export const Region = () => { + const { control } = useFormContext(); + + return ( + ( + + Region + + + + + The region where the Actor will be deployed. + + + + )} + /> + ); +}; + +// export const Tags = () => { +// // const setValues = useSetAtom(actorCustomTagValues); +// // const setKeys = useSetAtom(actorCustomTagKeys); + +// const { data: tags = [] } = useInfiniteQuery( +// useManagerQueries().actorsTagsQueryOptions(), +// ); + +// const keys = useMemo(() => { +// return Array.from( +// new Set(tags.flatMap((tag) => Object.keys(tag))), +// ).sort(); +// }, [tags]); +// const values = useMemo(() => { +// return Array.from( +// new Set(tags.flatMap((tag) => Object.values(tag))), +// ).sort(); +// }, [tags]); + +// return ( +//
+// +// ({ +// label: key, +// value: key, +// }))} +// values={values.map((value) => ({ +// label: value, +// value: value, +// }))} +// onCreateKeyOption={(value) => { +// // setKeys((old) => +// // Array.from(new Set([...old, value]).values()), +// // ); +// }} +// onCreateValueOption={(value) => { +// // setValues((old) => +// // Array.from(new Set([...old, value]).values()), +// // ); +// }} +// /> +//
+// ); +// }; diff --git a/frontend/apps/hub/src/domains/project/forms/build-tags-form.tsx b/frontend/src/components/actors/form/build-tags-form.tsx similarity index 92% rename from frontend/apps/hub/src/domains/project/forms/build-tags-form.tsx rename to frontend/src/components/actors/form/build-tags-form.tsx index ed06763268..723ce1404c 100644 --- a/frontend/apps/hub/src/domains/project/forms/build-tags-form.tsx +++ b/frontend/src/components/actors/form/build-tags-form.tsx @@ -1,22 +1,21 @@ -import { - Button, - Combobox, - FormControl, - FormFieldContext, - FormItem, - FormLabel, - FormMessage, - type ComboboxOption as Option, - Text, - createSchemaForm, -} from "@rivet-gg/components"; -import { Icon, faTrash } from "@rivet-gg/icons"; +import { faTrash, Icon } from "@rivet-gg/icons"; import { type UseFormReturn, useFieldArray, useFormContext, } from "react-hook-form"; import z from "zod"; +import { createSchemaForm } from "../../lib/create-schema-form"; +import { Button } from "../../ui/button"; +import { Combobox, type ComboboxOption as Option } from "../../ui/combobox"; +import { + FormControl, + FormFieldContext, + FormItem, + FormLabel, + FormMessage, +} from "../../ui/form"; +import { Text } from "../../ui/typography"; export const formSchema = z.object({ tags: z diff --git a/frontend/src/components/actors/form/go-to-actor-form.tsx b/frontend/src/components/actors/form/go-to-actor-form.tsx new file mode 100644 index 0000000000..a0b9595a2d --- /dev/null +++ b/frontend/src/components/actors/form/go-to-actor-form.tsx @@ -0,0 +1,45 @@ +import { type UseFormReturn, useFormContext } from "react-hook-form"; +import z from "zod"; +import { createSchemaForm } from "../../lib/create-schema-form"; +import { + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "../../ui/form"; +import { Input } from "../../ui/input"; +import { useActorsView } from "../actors-view-context-provider"; + +export const formSchema = z.object({ + actorId: z.string().nonempty("Actor ID is required").uuid(), +}); + +export type FormValues = z.infer; +export type SubmitHandler = ( + values: FormValues, + form: UseFormReturn, +) => Promise; + +const { Form, Submit } = createSchemaForm(formSchema); +export { Form, Submit }; + +export const ActorId = () => { + const { control } = useFormContext(); + const { copy } = useActorsView(); + return ( + ( + + {copy.actorId} + + + + + + )} + /> + ); +}; diff --git a/frontend/src/components/actors/get-started.tsx b/frontend/src/components/actors/get-started.tsx new file mode 100644 index 0000000000..9471f354cb --- /dev/null +++ b/frontend/src/components/actors/get-started.tsx @@ -0,0 +1,95 @@ +import { faActors, faFunction, faServer, Icon } from "@rivet-gg/icons"; +import { motion } from "framer-motion"; +import type { ComponentProps } from "react"; +import { DocsSheet } from "../docs-sheet"; +import { cn } from "../lib/utils"; +import { Button } from "../ui/button"; + +export function ActorsResources() { + return ( + <> +
+ + + +
+ + ); +} + +const linkVariants = { + hidden: { + opacity: 0, + }, + show: { + opacity: 1, + }, +}; + +interface ExampleLinkProps { + title: string; + description?: string; + icon: ComponentProps["icon"]; + href: string; + size?: "sm" | "md" | "lg"; +} + +function ExampleLink({ + title, + description, + icon, + href, + size = "lg", +}: ExampleLinkProps) { + return ( + + + + ); +} diff --git a/frontend/src/components/actors/getting-started.tsx b/frontend/src/components/actors/getting-started.tsx new file mode 100644 index 0000000000..63f60d6afa --- /dev/null +++ b/frontend/src/components/actors/getting-started.tsx @@ -0,0 +1,21 @@ +import { faActors, Icon } from "@rivet-gg/icons"; +import { useActorsView } from "./actors-view-context-provider"; +import { ActorsResources } from "./get-started"; + +export function GettingStarted() { + const { copy } = useActorsView(); + return ( +
+
+ +

+ {copy.gettingStarted.title} +

+

+ {copy.gettingStarted.description} +

+
+ +
+ ); +} diff --git a/frontend/src/components/actors/go-to-actor-button.tsx b/frontend/src/components/actors/go-to-actor-button.tsx new file mode 100644 index 0000000000..34e7769988 --- /dev/null +++ b/frontend/src/components/actors/go-to-actor-button.tsx @@ -0,0 +1,24 @@ +import { faMagnifyingGlass, Icon } from "@rivet-gg/icons"; +import { useNavigate } from "@tanstack/react-router"; +import { Button, type ButtonProps } from "@/components"; +import { useActorsView } from "./actors-view-context-provider"; + +export function GoToActorButton(props: ButtonProps) { + const navigate = useNavigate(); + const { copy } = useActorsView(); + return ( + + ); +} diff --git a/frontend/apps/hub/src/domains/project/components/group-project-select.tsx b/frontend/src/components/actors/group-project-select.tsx similarity index 94% rename from frontend/apps/hub/src/domains/project/components/group-project-select.tsx rename to frontend/src/components/actors/group-project-select.tsx index d1f7fa6c86..e71869a577 100644 --- a/frontend/apps/hub/src/domains/project/components/group-project-select.tsx +++ b/frontend/src/components/actors/group-project-select.tsx @@ -1,4 +1,6 @@ -import { groupProjectsQueryOptions } from "@/domains/project/queries"; +import { faCirclePlus, Icon } from "@rivet-gg/icons"; +import { useSuspenseQuery } from "@tanstack/react-query"; +import { type ComponentProps, useCallback } from "react"; import { Flex, Select, @@ -7,10 +9,8 @@ import { SelectSeparator, SelectTrigger, SelectValue, -} from "@rivet-gg/components"; -import { Icon, faCirclePlus } from "@rivet-gg/icons"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { type ComponentProps, useCallback } from "react"; +} from "@/components"; +import { groupProjectsQueryOptions } from "@/domains/project/queries"; interface GroupProjectSelectProps extends ComponentProps { groupId: string; diff --git a/frontend/src/components/actors/hooks/index.ts b/frontend/src/components/actors/hooks/index.ts new file mode 100644 index 0000000000..14c4d0400f --- /dev/null +++ b/frontend/src/components/actors/hooks/index.ts @@ -0,0 +1 @@ +export * from "./use-dialog"; diff --git a/frontend/src/components/actors/hooks/use-dialog.tsx b/frontend/src/components/actors/hooks/use-dialog.tsx new file mode 100644 index 0000000000..7c6cd19a0a --- /dev/null +++ b/frontend/src/components/actors/hooks/use-dialog.tsx @@ -0,0 +1,202 @@ +"use client"; +import { VisuallyHidden } from "@radix-ui/react-visually-hidden"; +import { + type ComponentProps, + type ComponentType, + lazy, + Suspense, + useCallback, + useMemo, + useState, +} from "react"; +import { Skeleton } from "@/components/ui/skeleton"; +import { + Dialog, + DialogContent, + type DialogProps, + DialogTitle, +} from "../../ui/dialog"; + +export interface DialogContentProps { + onClose?: () => void; +} + +interface DialogConfig { + autoFocus?: boolean; +} + +export const createDialogHook = < + // biome-ignore lint/suspicious/noExplicitAny: we don't know the type of the component, so we use any + Component extends Promise<{ default: ComponentType }>, +>( + component: Component, + opts: DialogConfig = {}, +) => { + const DialogImpl = ({ + dialogProps, + ...props + }: ComponentProps["default"]> & { + dialogProps?: DialogProps; + }) => { + // biome-ignore lint/correctness/useExhaustiveDependencies: component here is a static value, won't change over time + const Content = useMemo(() => lazy(() => component), []); + + return ( + + { + if (opts.autoFocus === false) { + return e.preventDefault(); + } + }} + > + + + Loading... + +
+ + +
+ +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ } + > + dialogProps?.onOpenChange?.(false)} + /> + + + + ); + }; + + const useHook = (props: ComponentProps["default"]>) => { + const [isOpen, setIsOpen] = useState(() => false); + + const close = useCallback(() => { + setIsOpen(false); + }, []); + + const open = useCallback(() => { + setIsOpen(true); + }, []); + + const handleOpenChange = useCallback((open: boolean) => { + setIsOpen(open); + }, []); + + return { + open, + close, + dialog: ( + + ), + }; + }; + + useHook.Dialog = DialogImpl; + + return useHook; +}; + +export const createDataDialogHook = < + const DataPropKeys extends string[], + // biome-ignore lint/suspicious/noExplicitAny: we don't know the type of the component, so we use any + Component extends Promise<{ default: ComponentType }>, +>( + _: DataPropKeys, + component: Component, + opts: DialogConfig = {}, +) => { + return ( + props: Omit< + ComponentProps["default"]>, + DataPropKeys[number] + >, + ) => { + const [isOpen, setIsOpen] = useState(false); + const [data, setData] = + useState< + Pick< + ComponentProps["default"]>, + DataPropKeys[number] + > + >(); + + const close = useCallback(() => { + setIsOpen(false); + }, []); + + const open = useCallback( + ( + data: Pick< + ComponentProps["default"]>, + DataPropKeys[number] + >, + ) => { + setIsOpen(true); + setData(data); + }, + [], + ); + + // biome-ignore lint/correctness/useExhaustiveDependencies: component here is a static value, won't change over time + const Content = useMemo(() => lazy(() => component), []); + + return { + open, + dialog: ( + + { + if (opts.autoFocus === false) { + return e.preventDefault(); + } + }} + > + + + + ), + }; + }; +}; + +export function useDialog() {} + +useDialog.GoToActor = createDialogHook(import("../dialogs/go-to-actor-dialog")); + +useDialog.Feedback = createDialogHook(import("../../dialogs/feedback-dialog")); +useDialog.CreateActor = createDialogHook( + import("../dialogs/create-actor-dialog"), +); diff --git a/packages/core/services/build/db/build/migrations/20200101000000_init.down.sql b/frontend/src/components/actors/hooks/use-websocket.ts similarity index 100% rename from packages/core/services/build/db/build/migrations/20200101000000_init.down.sql rename to frontend/src/components/actors/hooks/use-websocket.ts diff --git a/frontend/src/components/actors/index.ts b/frontend/src/components/actors/index.ts new file mode 100644 index 0000000000..f690e14fc4 --- /dev/null +++ b/frontend/src/components/actors/index.ts @@ -0,0 +1,18 @@ +export * from "./actor-context"; +export * from "./actor-not-found"; +export * from "./actor-queries-context"; +export * from "./actor-region"; +export * from "./actor-status-indicator"; +export * from "./actor-status-label"; +export * from "./actor-tags"; +export * from "./actors-actor-details"; +export * from "./actors-layout"; +export * from "./actors-layout-context"; +export * from "./actors-list-preview"; +export * from "./actors-view-context-provider"; +export * from "./console/actor-console-message"; +export * from "./console/actor-inspector"; +export * from "./getting-started"; +export * from "./hooks/index"; +export * from "./manager-context"; +export * from "./queries"; diff --git a/frontend/src/components/actors/manager-context.tsx b/frontend/src/components/actors/manager-context.tsx new file mode 100644 index 0000000000..d02ffc4efc --- /dev/null +++ b/frontend/src/components/actors/manager-context.tsx @@ -0,0 +1,365 @@ +import type { CreateActor as InspectorCreateActor } from "@rivetkit/core/inspector"; +import { + infiniteQueryOptions, + type MutationOptions, + type QueryClient, + queryOptions, +} from "@tanstack/react-query"; +import { createContext, useContext } from "react"; +import { z } from "zod"; +import { queryClient } from "@/queries/global"; +import { + type Actor, + type ActorId, + type ActorLogEntry, + type ActorMetrics, + type Build, + type CrashPolicy, + getActorStatus, + type Region, +} from "./queries"; + +export const ActorQueryOptionsSchema = z + .object({ + filters: z + .object({ + showDestroyed: z + .object({ value: z.array(z.string()) }) + .optional() + .catch(() => ({ value: ["false"] })), + id: z + .object({ + value: z.array(z.string()).optional(), + }) + .optional(), + key: z + .object({ + value: z.array(z.string()).optional(), + }) + .optional(), + }) + .optional() + .catch(() => ({})), + n: z + .array(z.string()) + .optional() + .catch(() => []), + }) + .optional(); +export type ActorQueryOptions = z.infer; + +export const ACTORS_PER_PAGE = 10; + +type PaginatedResponse = { + pagination: { cursor?: string | null }; +} & Record; + +type PaginatedActorResponse = PaginatedResponse; +type PaginatedBuildsResponse = PaginatedResponse; +type PaginatedRegionsResponse = PaginatedResponse; + +type CreateActor = Omit & { + runnerNameSelector: string; + key: string; + crashPolicy: CrashPolicy; +}; + +const defaultContext = { + endpoint: "", + features: { + canCreateActors: true, + canDeleteActors: false, + }, + actorsQueryOptions(opts: ActorQueryOptions) { + return infiniteQueryOptions({ + queryKey: ["actors", opts], + initialPageParam: undefined as string | undefined, + enabled: false, + refetchInterval: 2000, + queryFn: async () => { + return {} as PaginatedActorResponse; + }, + getNextPageParam: (lastPage) => { + if (lastPage.pagination.cursor) { + return lastPage.pagination.cursor; + } + + if ( + !lastPage || + lastPage.actors.length === 0 || + lastPage.actors.length < ACTORS_PER_PAGE + ) { + return undefined; + } + + return lastPage.actors[lastPage.actors.length - 1].id; + }, + }); + }, + + buildsQueryOptions() { + return infiniteQueryOptions({ + queryKey: ["actors", "builds"], + enabled: false, + initialPageParam: undefined as string | undefined, + refetchInterval: 2000, + queryFn: async () => { + return {} as PaginatedBuildsResponse; + }, + getNextPageParam: () => { + return undefined; + }, + select: (data) => { + return data.pages.flatMap((page) => page.builds); + }, + }); + }, + + buildsCountQueryOptions() { + return infiniteQueryOptions({ + ...this.buildsQueryOptions(), + select: (data) => { + return data.pages.reduce((acc, page) => { + return acc + page.builds.length; + }, 0); + }, + }); + }, + + actorsListQueryOptions(opts: ActorQueryOptions) { + return infiniteQueryOptions({ + ...this.actorsQueryOptions(opts), + enabled: (opts?.n || []).length > 0, + refetchInterval: 5000, + select: (data) => { + return data.pages.flatMap((page) => + page.actors.map((actor) => actor.id), + ); + }, + }); + }, + + actorsListPaginationQueryOptions(opts: ActorQueryOptions) { + return infiniteQueryOptions({ + ...this.actorsQueryOptions(opts), + select: (data) => { + return data.pages.flatMap((page) => + page.actors.map((actor) => actor.id), + ).length; + }, + }); + }, + + // #region Actor Queries + actorQueryOptions(actorId: ActorId) { + return queryOptions({ + queryFn: async () => { + return {} as Actor; + }, + queryKey: ["actor", actorId], + }); + }, + + actorRegionQueryOptions(actorId: ActorId) { + return queryOptions({ + ...this.actorQueryOptions(actorId), + select: (data) => data.region, + }); + }, + + actorDestroyedAtQueryOptions(actorId: ActorId) { + return queryOptions({ + ...this.actorQueryOptions(actorId), + select: (data) => + data.destroyedAt ? new Date(data.destroyedAt) : null, + }); + }, + + actorStatusQueryOptions(actorId: ActorId) { + return queryOptions({ + ...this.actorQueryOptions(actorId), + select: (data) => getActorStatus(data), + }); + }, + + actorFeaturesQueryOptions(actorId: ActorId) { + return queryOptions({ + ...this.actorQueryOptions(actorId), + select: (data) => data.features ?? [], + }); + }, + + actorGeneralQueryOptions(actorId: ActorId) { + return queryOptions({ + ...this.actorQueryOptions(actorId), + select: (data) => ({ + tags: data.tags, + keys: data.key, + createdAt: data.createdAt ? new Date(data.createdAt) : null, + destroyedAt: data.destroyedAt + ? new Date(data.destroyedAt) + : null, + connectableAt: data.connectableAt + ? new Date(data.connectableAt) + : null, + pendingAllocationAt: data.pendingAllocationAt + ? new Date(data.pendingAllocationAt) + : null, + sleepingAt: data.sleepingAt ? new Date(data.sleepingAt) : null, + region: data.region, + crashPolicy: data.crashPolicy, + }), + }); + }, + actorBuildQueryOptions(actorId: ActorId) { + return queryOptions({ + queryKey: ["actor", actorId, "build"], + queryFn: async () => { + return {} as Build; + }, + enabled: false, + }); + }, + actorMetricsQueryOptions(actorId: ActorId) { + return queryOptions({ + queryKey: ["actor", actorId, "metrics"], + queryFn: async () => { + return {} as ActorMetrics; + }, + enabled: false, + }); + }, + actorKeysQueryOptions(actorId: ActorId) { + return queryOptions({ + ...this.actorQueryOptions(actorId), + select: (data) => data.key, + }); + }, + actorDestroyMutationOptions(actorId: ActorId) { + return { + mutationKey: ["actor", actorId, "destroy"], + mutationFn: async () => { + return; + }, + onSuccess: () => { + const keys = this.actorQueryOptions(actorId).queryKey.filter( + (k) => typeof k === "string", + ); + queryClient.invalidateQueries({ + predicate: (query) => { + return keys.every((k) => query.queryKey.includes(k)); + }, + }); + }, + } satisfies MutationOptions; + }, + actorLogsQueryOptions(actorId: ActorId) { + return infiniteQueryOptions({ + queryKey: ["actor", actorId, "logs"], + initialPageParam: null as string | null, + queryFn: async () => { + return [] as ActorLogEntry[]; + }, + getNextPageParam: () => null, + }); + }, + actorNetworkQueryOptions(actorId: ActorId) { + return queryOptions({ + ...this.actorQueryOptions(actorId), + select: (data) => data.network, + }); + }, + actorNetworkPortsQueryOptions(actorId: ActorId) { + return queryOptions({ + ...this.actorNetworkQueryOptions(actorId), + select: (data) => data.network?.ports, + }); + }, + actorRuntimeQueryOptions(actorId: ActorId) { + return queryOptions({ + ...this.actorQueryOptions(actorId), + select: ({ runtime, lifecycle, resources, tags }) => ({ + runtime, + lifecycle, + resources, + tags, + }), + }); + }, + actorWorkerQueryOptions(actorId: ActorId) { + return queryOptions({ + ...this.actorQueryOptions(actorId), + select: (data) => ({ + features: data.features ?? [], + name: data.name ?? null, + endpoint: this.endpoint ?? null, + destroyedAt: data.destroyedAt + ? new Date(data.destroyedAt) + : null, + startedAt: data.startedAt ? new Date(data.startedAt) : null, + }), + }); + }, + // #endregion + regionsQueryOptions() { + return infiniteQueryOptions({ + queryKey: ["actor", "regions"], + initialPageParam: null as string | null, + queryFn: async () => { + return {} as PaginatedRegionsResponse; + }, + getNextPageParam: () => null, + select: (data) => data.pages.flatMap((page) => page.regions), + }); + }, + regionQueryOptions(regionId: string) { + return queryOptions({ + queryKey: ["actor", "region", regionId], + enabled: !!regionId, + queryFn: async () => { + return {} as Region; + }, + }); + }, + managerStatusQueryOptions() { + return queryOptions({ + queryKey: ["managerStatus"], + refetchInterval: 1000, + enabled: false, + retry: 0, + queryFn: async () => { + return false as boolean; + }, + }); + }, + createActorMutationOptions() { + return { + mutationKey: ["createActor"], + mutationFn: async (_: CreateActor) => { + return ""; + }, + onSuccess: () => { + const keys = this.actorsQueryOptions({}).queryKey.filter( + (k) => typeof k === "string", + ); + queryClient.invalidateQueries({ + predicate: (query) => { + return keys.every((k) => query.queryKey.includes(k)); + }, + }); + }, + }; + }, +}; + +export type ManagerContext = typeof defaultContext; + +export function createDefaultManagerContext(): ManagerContext { + return defaultContext; +} + +const ManagerContext = createContext({} as ManagerContext); + +export const useManager = () => useContext(ManagerContext); + +export const ManagerProvider = ManagerContext.Provider; diff --git a/frontend/apps/hub/src/domains/project/components/matchmaker-lobby-config-settings-card.tsx b/frontend/src/components/actors/matchmaker-lobby-config-settings-card.tsx similarity index 97% rename from frontend/apps/hub/src/domains/project/components/matchmaker-lobby-config-settings-card.tsx rename to frontend/src/components/actors/matchmaker-lobby-config-settings-card.tsx index c6112dea98..52e564ad1e 100644 --- a/frontend/apps/hub/src/domains/project/components/matchmaker-lobby-config-settings-card.tsx +++ b/frontend/src/components/actors/matchmaker-lobby-config-settings-card.tsx @@ -1,4 +1,4 @@ -import * as MatchmakerLobbyConfigForm from "@/domains/project/forms/matchmaker-lobby-config-form"; +import { useSuspenseQuery } from "@tanstack/react-query"; import { Card, CardContent, @@ -6,8 +6,8 @@ import { CardHeader, CardTitle, Flex, -} from "@rivet-gg/components"; -import { useSuspenseQuery } from "@tanstack/react-query"; +} from "@/components"; +import * as MatchmakerLobbyConfigForm from "@/domains/project/forms/matchmaker-lobby-config-form"; import { useMatchmakerLobbyConfigFormHandler } from "../hooks/use-matchmaker-lobby-config-form-handler"; import { projectEnvironmentQueryOptions } from "../queries"; diff --git a/frontend/apps/hub/src/domains/project/components/project-builds-table-actions.tsx b/frontend/src/components/actors/project-builds-table-actions.tsx similarity index 91% rename from frontend/apps/hub/src/domains/project/components/project-builds-table-actions.tsx rename to frontend/src/components/actors/project-builds-table-actions.tsx index 47dcea2344..5631c84cfd 100644 --- a/frontend/apps/hub/src/domains/project/components/project-builds-table-actions.tsx +++ b/frontend/src/components/actors/project-builds-table-actions.tsx @@ -1,12 +1,12 @@ +import { faEllipsisH, Icon } from "@rivet-gg/icons"; +import { useNavigate } from "@tanstack/react-router"; import { Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, -} from "@rivet-gg/components"; -import { Icon, faEllipsisH } from "@rivet-gg/icons"; -import { useNavigate } from "@tanstack/react-router"; +} from "@/components"; interface ProjectBuildsTableActionsProps { buildId: string; diff --git a/frontend/apps/hub/src/domains/project/components/project-environments-table-actions.tsx b/frontend/src/components/actors/project-environments-table-actions.tsx similarity index 86% rename from frontend/apps/hub/src/domains/project/components/project-environments-table-actions.tsx rename to frontend/src/components/actors/project-environments-table-actions.tsx index b6722a6274..8534fa0bfa 100644 --- a/frontend/apps/hub/src/domains/project/components/project-environments-table-actions.tsx +++ b/frontend/src/components/actors/project-environments-table-actions.tsx @@ -1,11 +1,11 @@ +import { faEllipsisH, Icon } from "@rivet-gg/icons"; import { Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, -} from "@rivet-gg/components"; -import { Icon, faEllipsisH } from "@rivet-gg/icons"; +} from "@/components"; export function ProjectEnvironmentsTableActions() { return ( diff --git a/frontend/apps/hub/src/domains/project/components/project-logo-settings-card.tsx b/frontend/src/components/actors/project-logo-settings-card.tsx similarity index 97% rename from frontend/apps/hub/src/domains/project/components/project-logo-settings-card.tsx rename to frontend/src/components/actors/project-logo-settings-card.tsx index e4ede8afde..a2a6185e39 100644 --- a/frontend/apps/hub/src/domains/project/components/project-logo-settings-card.tsx +++ b/frontend/src/components/actors/project-logo-settings-card.tsx @@ -1,11 +1,11 @@ -import * as GroupImageForm from "@/domains/project/forms/project-logo-form"; import { Card, CardContent, CardFooter, CardHeader, CardTitle, -} from "@rivet-gg/components"; +} from "@/components"; +import * as GroupImageForm from "@/domains/project/forms/project-logo-form"; import { useProjectLogoUploadMutation } from "../queries"; interface ProjectLogoSettingsCardProps { diff --git a/frontend/apps/hub/src/domains/project/components/project-select.tsx b/frontend/src/components/actors/project-select.tsx similarity index 96% rename from frontend/apps/hub/src/domains/project/components/project-select.tsx rename to frontend/src/components/actors/project-select.tsx index 1438de3313..0560643252 100644 --- a/frontend/apps/hub/src/domains/project/components/project-select.tsx +++ b/frontend/src/components/actors/project-select.tsx @@ -1,5 +1,6 @@ -import { GroupAvatar } from "@/domains/group/components/group-avatar"; -import { projectsByGroupQueryOptions } from "@/domains/project/queries"; +import { faCirclePlus, Icon } from "@rivet-gg/icons"; +import { useSuspenseQuery } from "@tanstack/react-query"; +import { type ComponentProps, Fragment, useCallback } from "react"; import { Flex, Select, @@ -10,10 +11,9 @@ import { SelectSeparator, SelectTrigger, SelectValue, -} from "@rivet-gg/components"; -import { Icon, faCirclePlus } from "@rivet-gg/icons"; -import { useSuspenseQuery } from "@tanstack/react-query"; -import { type ComponentProps, Fragment, useCallback } from "react"; +} from "@/components"; +import { GroupAvatar } from "@/domains/group/components/group-avatar"; +import { projectsByGroupQueryOptions } from "@/domains/project/queries"; interface ProjectSelectProps extends ComponentProps { showCreateProject?: boolean; diff --git a/frontend/apps/hub/src/domains/project/components/project-table-actions.tsx b/frontend/src/components/actors/project-table-actions.tsx similarity index 86% rename from frontend/apps/hub/src/domains/project/components/project-table-actions.tsx rename to frontend/src/components/actors/project-table-actions.tsx index bd462c5d44..064f2f5e0d 100644 --- a/frontend/apps/hub/src/domains/project/components/project-table-actions.tsx +++ b/frontend/src/components/actors/project-table-actions.tsx @@ -1,11 +1,11 @@ +import { faEllipsisH, Icon } from "@rivet-gg/icons"; import { Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, -} from "@rivet-gg/components"; -import { Icon, faEllipsisH } from "@rivet-gg/icons"; +} from "@/components"; export function ProjectTableActions() { return ( diff --git a/frontend/apps/hub/src/domains/project/components/project-tile.tsx b/frontend/src/components/actors/project-tile.tsx similarity index 86% rename from frontend/apps/hub/src/domains/project/components/project-tile.tsx rename to frontend/src/components/actors/project-tile.tsx index 90d412f28d..835d613b2b 100644 --- a/frontend/apps/hub/src/domains/project/components/project-tile.tsx +++ b/frontend/src/components/actors/project-tile.tsx @@ -1,5 +1,5 @@ -import type { Rivet } from "@rivet-gg/api-full"; -import { AssetImage, Flex, Text } from "@rivet-gg/components"; +import type { Rivet } from "@rivet-gg/api"; +import { AssetImage, Flex, Text } from "@/components"; import { BillingPlanBadge } from "./billing/billing-plan-badge"; interface ProjectTileProps diff --git a/frontend/src/components/actors/queries/actor.ts b/frontend/src/components/actors/queries/actor.ts new file mode 100644 index 0000000000..3d5fc0982c --- /dev/null +++ b/frontend/src/components/actors/queries/actor.ts @@ -0,0 +1,218 @@ +import { fetchEventSource } from "@microsoft/fetch-event-source"; +import type { + ActorId, + Patch, + RecordedRealtimeEvent, +} from "@rivetkit/core/inspector"; +import { useMutation, useQueryClient } from "@tanstack/react-query"; +import { applyPatch, compare } from "fast-json-patch"; +import { useCallback, useEffect, useMemo } from "react"; +import { useActor } from "../actor-queries-context"; + +export const useActorClearEventsMutation = ( + actorId: ActorId, + options?: Parameters[1], +) => { + const queryClient = useQueryClient(); + const queries = useActor(); + return useMutation({ + ...queries.actorClearEventsMutationOptions(actorId), + onMutate: async () => { + queryClient.setQueryData( + queries.actorEventsQueryOptions(actorId).queryKey, + () => ({ events: [] }), + ); + }, + ...options, + }); +}; + +export const useActorStatePatchMutation = ( + actorId: ActorId, + options?: Parameters[1], +) => { + const queryClient = useQueryClient(); + const queries = useActor(); + return useMutation({ + // biome-ignore lint/suspicious/noExplicitAny: its really any + mutationFn: async (data: any) => { + const client = queries.createActorInspector(actorId); + + const oldStateQuery = queryClient.getQueryData( + queries.actorStateQueryOptions(actorId).queryKey, + ); + + const oldState = oldStateQuery?.state; + + let response: Awaited>; + + if (!oldState || !isPatchable(data)) { + response = await client.state.$patch({ + // its okay, we know the type + // @ts-expect-error + json: { replace: data }, + }); + } else { + const patches = compare(oldState, data); + response = await client.state.$patch({ + // its okay, we know the type + // @ts-expect-error + json: { patch: patches }, + }); + } + + if (!response.ok) { + throw response; + } + return await response.json(); + }, + onSuccess: (data) => { + queryClient.setQueryData( + queries.actorStateQueryOptions(actorId).queryKey, + data, + ); + }, + ...options, + }); +}; + +const getHeaders = ( + v: + | Record + | (() => Record | Promise>), +) => { + if (typeof v === "function") { + return v(); + } + return v; +}; + +function useStream( + actorId: ActorId, + onMessage: (data: T) => void, + url: string, + opts: { enabled: boolean } = { enabled: true }, +) { + const stableOnMessage = useCallback(onMessage, []); + const queries = useActor(); + + useEffect(() => { + const controller = new AbortController(); + + if (!opts.enabled) { + controller.abort(); + return () => controller.abort(); + } + + async function establishConnection() { + fetchEventSource(url, { + signal: controller.signal, + headers: await getHeaders( + queries.createActorInspectorFetchConfiguration(actorId) + ?.headers || {}, + ), + onmessage: (event) => { + const msg = JSON.parse(event.data); + stableOnMessage(msg); + }, + onclose: async () => { + await new Promise((resolve) => setTimeout(resolve, 1000)); + controller.signal.throwIfAborted(); + establishConnection(); + }, + }).catch((error) => console.error(error)); + } + + establishConnection(); + return () => { + controller.abort(); + }; + }, [url, actorId, opts.enabled, stableOnMessage]); +} + +export const useActorStateStream = ( + actorId: ActorId, + opts: { enabled: boolean } = { enabled: true }, +) => { + const queryClient = useQueryClient(); + const queries = useActor(); + + useStream( + actorId, + useCallback( + (data: unknown) => { + queryClient.setQueryData( + queries.actorStateQueryOptions(actorId).queryKey, + () => ({ enabled: true, state: data }), + ); + }, + [queryClient, actorId, queries], + ), + useMemo( + () => + queries.createActorInspector(actorId).state.stream.$url().href, + [actorId, queries], + ), + opts, + ); +}; + +export const useActorConnectionsStream = (actorId: ActorId) => { + const queryClient = useQueryClient(); + const queries = useActor(); + + useStream( + actorId, + useCallback( + (data) => { + queryClient.setQueryData( + queries.actorConnectionsQueryOptions(actorId).queryKey, + () => ({ enabled: true, connections: data }), + ); + }, + [queryClient, actorId, queries], + ), + useMemo( + () => + queries.createActorInspector(actorId).connections.stream.$url() + .href, + [actorId, queries], + ), + ); +}; + +export const useActorEventsStream = ( + actorId: ActorId, + opts: { enabled: boolean }, +) => { + const queryClient = useQueryClient(); + const queries = useActor(); + + useStream( + actorId, + useCallback( + (data: RecordedRealtimeEvent[]) => { + queryClient.setQueryData( + queries.actorEventsQueryOptions(actorId).queryKey, + () => { + return { events: data }; + }, + ); + }, + [queryClient, actorId, queries], + ), + useMemo( + () => + queries.createActorInspector(actorId).events.stream.$url().href, + [actorId, queries], + ), + opts, + ); +}; + +/** + * Check if the object is patchable, i.e. if it is an object and not null. + */ +function isPatchable(data: unknown) { + return typeof data === "object" && data !== null; +} diff --git a/frontend/src/components/actors/queries/index.ts b/frontend/src/components/actors/queries/index.ts new file mode 100644 index 0000000000..8726acfa66 --- /dev/null +++ b/frontend/src/components/actors/queries/index.ts @@ -0,0 +1,129 @@ +import type { Actor as InspectorActor } from "@rivetkit/core/inspector"; +import type { NamespaceNameId } from "@/queries/manager-engine"; + +export type { ActorLogEntry } from "@rivetkit/core/inspector"; +export { ActorFeature } from "@rivetkit/core/inspector"; + +import type { ActorId } from "@rivetkit/core/inspector"; + +export type { ActorId }; + +export type PortRouting = { + guard?: {}; + host?: {}; +}; + +export type Port = { + protocol: "http" | "https" | "tcp" | "tcp_tls" | "udp"; + internalPort?: number; + hostname?: string; + port?: number; + path?: string; + /** Fully formed connection URL including protocol, hostname, port, and path, if applicable. */ + url?: string; + routing: PortRouting; +}; + +export type Runtime = { + build: string; + arguments?: string[]; + environment?: Record; +}; + +export type Lifecycle = { + /** The duration to wait for in milliseconds before killing the actor. This should be set to a safe default, and can be overridden during a DELETE request if needed. */ + killTimeout?: number; + /** If true, the actor will try to reschedule itself automatically in the event of a crash or a datacenter failover. The actor will not reschedule if it exits successfully. */ + durable?: boolean; +}; + +export type Resources = { + /** + * The number of CPU cores in millicores, or 1/1000 of a core. For example, + * 1/8 of a core would be 125 millicores, and 1 core would be 1000 + * millicores. + */ + cpu: number; + /** The amount of memory in megabytes */ + memory: number; +}; + +export type Actor = Omit & { + network?: { + mode: "bridge" | "host"; + ports: Record; + }; + runtime?: Runtime; + lifecycle?: Lifecycle; + key: string | undefined; + + // engine related + runner?: string; + crashPolicy?: CrashPolicy; + sleepingAt?: string | null; + connectableAt?: string | null; + pendingAllocationAt?: string | null; +} & { id: ActorId }; + +export enum CrashPolicy { + Restart = "restart", + Sleep = "sleep", + Destroy = "destroy", +} + +export type ActorMetrics = { + metrics: Record; + rawData: Record; + interval: number; +}; + +export type Build = { + id: string; + name: string; +}; + +export type Region = { + id: string; + name: string; +}; + +export * from "./actor"; + +export type ActorStatus = + | "starting" + | "running" + | "stopped" + | "crashed" + | "sleeping" + | "unknown"; + +export function getActorStatus( + actor: Pick< + Actor, + "createdAt" | "startedAt" | "destroyedAt" | "sleepingAt" + >, +): ActorStatus { + const { createdAt, startedAt, destroyedAt, sleepingAt } = actor; + + if (createdAt && sleepingAt && !destroyedAt) { + return "sleeping"; + } + + if (createdAt && !startedAt && !destroyedAt) { + return "starting"; + } + + if (createdAt && startedAt && !destroyedAt) { + return "running"; + } + + if (createdAt && startedAt && destroyedAt) { + return "stopped"; + } + + if (createdAt && !startedAt && destroyedAt) { + return "crashed"; + } + + return "unknown"; +} diff --git a/frontend/src/components/actors/region-select.tsx b/frontend/src/components/actors/region-select.tsx new file mode 100644 index 0000000000..cfc4ade905 --- /dev/null +++ b/frontend/src/components/actors/region-select.tsx @@ -0,0 +1,57 @@ +import { useInfiniteQuery } from "@tanstack/react-query"; +import { Combobox } from "@/components"; +import { ActorRegion } from "./actor-region"; +import { useManager } from "./manager-context"; + +interface RegionSelectProps { + onValueChange: (value: string) => void; + value: string; +} + +export function RegionSelect({ onValueChange, value }: RegionSelectProps) { + const { + data = [], + fetchNextPage, + isLoading, + isFetchingNextPage, + } = useInfiniteQuery(useManager().regionsQueryOptions()); + + const regions = [ + { + label: Automatic (Recommended), + value: "auto", + region: { id: "auto", name: "Automatic (Recommended)" }, + }, + ...data.map((region) => { + return { + label: + region.name === "local" ? ( + + ) : ( + region.name + ), + value: region.id, + region, + }; + }), + ]; + + return ( + { + const search = searchMixed.toLowerCase(); + return ( + option.region.id.includes(search) || + option.region.name.includes(search) + ); + }} + className="w-full" + /> + ); +} diff --git a/frontend/src/components/actors/root-layout-context.tsx b/frontend/src/components/actors/root-layout-context.tsx new file mode 100644 index 0000000000..3c2e64424a --- /dev/null +++ b/frontend/src/components/actors/root-layout-context.tsx @@ -0,0 +1,42 @@ +import type { ReactNode, RefObject } from "react"; +import { createContext, useContext, useMemo } from "react"; +import { assertNonNullable, type ImperativePanelHandle } from "@/components"; + +export interface RootLayoutContextValue { + sidebarRef: RefObject; + isSidebarCollapsed: boolean; +} + +export const RootLayoutContext = createContext( + null, +); + +interface RootLayoutProviderProps extends RootLayoutContextValue { + children: ReactNode; +} + +export function RootLayoutContextProvider({ + children, + sidebarRef, + isSidebarCollapsed, +}: RootLayoutProviderProps) { + return ( + ({ + sidebarRef, + isSidebarCollapsed, + }), + [sidebarRef, isSidebarCollapsed], + )} + > + {children} + + ); +} + +export function useRootLayout() { + const context = useContext(RootLayoutContext); + assertNonNullable(context); + return context; +} diff --git a/frontend/src/components/actors/runner-select.tsx b/frontend/src/components/actors/runner-select.tsx new file mode 100644 index 0000000000..c8f8d0908d --- /dev/null +++ b/frontend/src/components/actors/runner-select.tsx @@ -0,0 +1,72 @@ +import { useInfiniteQuery } from "@tanstack/react-query"; +import { useMemo, useState } from "react"; +import { Combobox } from "@/components"; +import { + type NamespaceNameId, + runnerNamesQueryOptions, +} from "@/queries/manager-engine"; + +interface RunnerSelectProps { + onValueChange: (value: string) => void; + value: string; + namespace: NamespaceNameId; +} + +export function RunnerSelect({ + onValueChange, + value, + namespace, +}: RunnerSelectProps) { + const { + data = [], + hasNextPage, + fetchNextPage, + isLoading, + isFetchingNextPage, + } = useInfiniteQuery(runnerNamesQueryOptions({ namespace })); + + const [newRunner, setNewRunner] = useState(null); + + const builds = useMemo(() => { + const runners = data.map((runner) => { + return { + label: runner, + value: runner, + }; + }); + + if (newRunner) { + runners.push({ + label: newRunner, + value: newRunner, + }); + } + + return runners; + }, [data, newRunner]); + + const handleNewSelect = (value: string) => { + setNewRunner(value); + }; + + const handleValueChange = (value: string) => { + if (value !== newRunner) { + setNewRunner(null); + } + onValueChange(value); + }; + + return ( + + ); +} diff --git a/frontend/src/components/actors/worker/actor-repl.worker.ts b/frontend/src/components/actors/worker/actor-repl.worker.ts new file mode 100644 index 0000000000..8478653a4b --- /dev/null +++ b/frontend/src/components/actors/worker/actor-repl.worker.ts @@ -0,0 +1,209 @@ +import { createClient } from "@rivetkit/actor/client"; +import { fromJs } from "esast-util-from-js"; +import { toJs } from "estree-util-to-js"; +import { + createHighlighterCore, + createOnigurumaEngine, + type HighlighterCore, +} from "shiki"; +import { getConfig } from "@/components"; +import { createEngineActorContext } from "@/queries/actor-engine"; +import { + type InitMessage, + MessageSchema, + type ReplErrorCode, + type Response, + ResponseSchema, +} from "./actor-worker-schema"; + +class ReplError extends Error { + constructor( + public readonly code: ReplErrorCode, + message: string, + ) { + super(message); + } + + static unsupported() { + return new ReplError("unsupported", "Actor unsupported"); + } +} + +export let highlighter: HighlighterCore | undefined; + +async function formatCode(code: string) { + highlighter ??= await createHighlighterCore({ + themes: [import("shiki/themes/github-dark-default.mjs")], + langs: [import("@shikijs/langs/typescript")], + engine: createOnigurumaEngine(import("shiki/wasm")), + }); + + return highlighter.codeToTokens(code, { + lang: "typescript", + theme: "github-dark-default", + }); +} + +const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); + +async function evaluateCode(code: string, args: Record) { + const argsString = Object.keys(args); + const argValues = Object.values(args); + + let jsCode: ReturnType; + try { + const program = fromJs(code, { + module: true, + allowAwaitOutsideFunction: true, + allowReturnOutsideFunction: true, + }); + + const lastStatement = program.body[program.body.length - 1]; + if (lastStatement.type === "ExpressionStatement") { + program.body[program.body.length - 1] = { + type: "ReturnStatement", + argument: lastStatement.expression, + }; + } + + jsCode = toJs(program); + } catch (e) { + throw new ReplError("syntax", "Syntax error"); + } + + return new Function( + "window", + ...argsString, + `"use strict"; + return (async () => { + ${jsCode.value} + })() + `, + )({}, ...argValues); +} + +const createConsole = (id: string) => { + return new Proxy( + { ...console }, + { + get(target, prop) { + return (...args: unknown[]) => { + respond({ + type: "log", + id, + data: { + method: prop as "log" | "warn" | "error", + data: args, + timestamp: new Date().toISOString(), + }, + }); + return Reflect.get(target, prop)(...args); + }; + }, + }, + ); +}; + +let init: null | Omit = null; + +addEventListener("message", async (event) => { + const { success, error, data } = MessageSchema.safeParse(event.data); + + if (!success) { + console.error("Malformed message", event.data, error); + return; + } + + if (data.type === "init") { + init = { + rpcs: data.rpcs ?? [], + endpoint: data.endpoint, + name: data.name, + id: data.id, + }; + respond({ + type: "ready", + }); + return; + } + + if (data.type === "code") { + const actor = init; + if (!actor) { + respond({ + type: "error", + data: new Error("Actor not initialized"), + }); + return; + } + + try { + const formatted = await formatCode(data.data); + respond({ + type: "formatted", + id: data.id, + data: formatted, + }); + + const createRpc = + (rpc: string) => + async (...args: unknown[]) => { + const response = await callAction({ name: rpc, args }); + return response; + }; + + const exposedActor = Object.fromEntries( + actor.rpcs?.map((rpc) => [rpc, createRpc(rpc)]) ?? [], + ); + + const evaluated = await evaluateCode(data.data, { + console: createConsole(data.id), + wait, + actor: exposedActor, + }); + return respond({ + type: "result", + id: data.id, + data: evaluated, + }); + } catch (e) { + return respond({ + type: "error", + id: data.id, + data: e, + }); + } + } +}); + +function respond(msg: Response) { + return postMessage(ResponseSchema.parse(msg)); +} + +async function callAction({ name, args }: { name: string; args: unknown[] }) { + if (!init) throw new Error("Actor not initialized"); + + if (__APP_TYPE__ === "inspector") { + const client = createClient(init.endpoint).getForId(init.name, init.id); + return await client.action({ name, args }); + } + + const opts = + createEngineActorContext().createActorInspectorFetchConfiguration( + init.id, + ); + + const response = await fetch(`${getConfig().apiUrl}/actions/${name}`, { + ...opts, + headers: { + ...opts.headers, + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + throw response; + } + + return await response.json(); +} diff --git a/frontend/src/components/actors/worker/actor-worker-container.ts b/frontend/src/components/actors/worker/actor-worker-container.ts new file mode 100644 index 0000000000..c928583b44 --- /dev/null +++ b/frontend/src/components/actors/worker/actor-worker-container.ts @@ -0,0 +1,271 @@ +import { CancelledError } from "@tanstack/react-query"; +import ActorWorker from "./actor-repl.worker?worker"; +import { + type CodeMessage, + type FormattedCode, + type InitMessage, + type Log, + ResponseSchema, +} from "./actor-worker-schema"; + +export type ReplCommand = { + logs: Log[]; + code: string; + key: string; + inputTimestamp?: string; + outputTimestamp?: string; +} & ( + | { status: "pending" } + | { status: "formatted"; formatted: FormattedCode } + | { status: "success"; formatted: FormattedCode; result: unknown } + | { status: "error"; formatted: FormattedCode | undefined; error: unknown } +); + +export type ContainerStatus = + | { type: "ready" } + | { type: "error"; error: unknown } + | { type: "pending" } + | { type: "unsupported"; error: unknown } + | { type: "unknown" }; + +export type ContainerState = { + status: ContainerStatus; + commands: ReplCommand[]; +}; + +export class ActorWorkerContainer { + #state: ContainerState = { + status: { type: "unknown" }, + commands: [], + }; + + #meta: { + actorId: string; + rpcs: string[]; + endpoint?: string; + name?: string; + } | null = null; + + #listeners: (() => void)[] = []; + #worker: Worker | undefined; + + // + async init({ + actorId, + signal, + rpcs = [], + endpoint, + name, + }: { + actorId: string; + signal: AbortSignal; + rpcs?: string[]; + endpoint?: string; + name?: string; + }) { + this.terminate(); + + this.#meta = { actorId, rpcs, endpoint, name }; + this.#state.status = { type: "pending" }; + this.#update(); + try { + signal.throwIfAborted(); + + // FIXME(RVT-4553) + // if (actor.resources.cpu !== 125 || actor.resources.memory !== 128) { + // throw new Error("Unsupported actor resources"); + // } + + // If we reached this point, the actor is supported + // check if we still operate on the same actor + if (this.#meta.actorId !== actorId) { + // if not, we don't need to do anything + return null; + } + + const worker = new ActorWorker({ name: `actor-${actorId}` }); + signal.throwIfAborted(); + // now worker needs to check if the actor is supported + this.#setupWorker(worker); + signal.throwIfAborted(); + return worker; + } catch (e) { + console.log(e); + // If we reached this point, the actor is not supported + // check if we still operate on the same actor + if (e instanceof DOMException && e.name === "AbortError") { + return null; + } + + if (e instanceof CancelledError) { + this.#worker?.terminate(); + this.#worker = undefined; + return null; + } + + this.#worker?.terminate(); + this.#worker = undefined; + this.#state.status = { type: "unsupported", error: e }; + this.#update(); + } + return null; + } + + terminate() { + this.#worker?.terminate(); + this.#worker = undefined; + this.#state.commands = []; + this.#state.status = { type: "unknown" }; + this.#meta = null; + this.#update(); + } + + #setupWorker(worker: Worker) { + this.#worker = worker; + this.#worker.addEventListener("message", (event) => { + try { + this.#handleMessage(event); + } catch (e) { + console.error(e); + this.#state.status = { type: "error", error: e }; + this.#update(); + } + }); + + this.#worker.addEventListener("error", (error) => { + console.log(error, error.message, error.error); + }); + + this.#worker.postMessage({ + type: "init", + rpcs: this.#meta?.rpcs ?? [], + id: this.#meta?.actorId ?? "", + endpoint: this.#meta?.endpoint ?? "", + name: this.#meta?.name ?? "", + } satisfies InitMessage); + } + + run(data: string) { + const key = Date.now().toString(); + this.#state.commands = [ + ...this.#state.commands, + { status: "pending", code: data, key, logs: [] }, + ]; + + this.#worker?.postMessage({ + type: "code", + data, + id: key, + } satisfies CodeMessage); + this.#update(); + } + + getCommands() { + return this.#state.commands; + } + + getStatus() { + return this.#state.status; + } + + subscribe(cb: () => void) { + this.#listeners.push(cb); + return () => { + this.#listeners = this.#listeners.filter( + (listener) => listener !== cb, + ); + }; + } + + #handleMessage(event: MessageEvent) { + const { success, data: msg } = ResponseSchema.safeParse(event.data); + + if (!success) { + return; + } + + if (msg.type === "formatted") { + const command = this.#state.commands.find( + (command) => command.key === msg.id, + ); + if (command) { + const newCommand = { + inputTimestamp: new Date().toISOString(), + ...command, + status: "formatted", + formatted: msg.data, + } satisfies ReplCommand; + Object.assign(command, newCommand); + this.#state.commands = [...this.#state.commands]; + this.#update(); + } + } + + if (msg.type === "result") { + const command = this.#state.commands.find( + (command) => command.key === msg.id, + ); + if (command) { + const newCommand = { + outputTimestamp: new Date().toISOString(), + ...command, + status: "success", + result: msg.data, + }; + Object.assign(command, newCommand); + this.#state.commands = [...this.#state.commands]; + this.#update(); + } + } + + if (msg.type === "log") { + const command = this.#state.commands.find( + (command) => command.key === msg.id, + ); + if (command) { + const newCommand = { + ...command, + logs: [...command.logs, msg.data], + }; + Object.assign(command, newCommand); + this.#state.commands = [...this.#state.commands]; + this.#update(); + } + } + + if (msg.type === "error") { + if (!msg.id) { + this.#state.status = { type: "error", error: msg.data }; + console.error("Actor Worker Error", msg.data); + this.#update(); + return; + } + + const command = this.#state.commands.find( + (command) => command.key === msg.id, + ); + if (command) { + const newCommand = { + outputTimestamp: new Date().toISOString(), + ...command, + status: "error", + error: msg.data, + }; + Object.assign(command, newCommand); + this.#state.commands = [...this.#state.commands]; + this.#update(); + } + } + + if (msg.type === "ready") { + this.#state.status = { type: "ready" }; + this.#update(); + } + } + + #update() { + for (const listener of this.#listeners) { + listener(); + } + } +} diff --git a/frontend/src/components/actors/worker/actor-worker-context.tsx b/frontend/src/components/actors/worker/actor-worker-context.tsx new file mode 100644 index 0000000000..bff0fb3fb8 --- /dev/null +++ b/frontend/src/components/actors/worker/actor-worker-context.tsx @@ -0,0 +1,107 @@ +import { useQuery } from "@tanstack/react-query"; +import { + createContext, + type ReactNode, + useCallback, + useContext, + useEffect, + useState, + useSyncExternalStore, +} from "react"; +import { assertNonNullable } from "../../lib/utils"; +import { useActor } from "../actor-queries-context"; +import { useManager } from "../manager-context"; +import { ActorFeature, type ActorId } from "../queries"; +import { ActorWorkerContainer } from "./actor-worker-container"; + +export const ActorWorkerContext = createContext( + null, +); + +export const useActorWorker = () => { + const value = useContext(ActorWorkerContext); + assertNonNullable(value); + return value; +}; + +interface ActorWorkerContextProviderProps { + actorId: ActorId; + children: ReactNode; +} +export const ActorWorkerContextProvider = ({ + children, + actorId, +}: ActorWorkerContextProviderProps) => { + const { data: { features, name, endpoint, destroyedAt, startedAt } = {} } = + useQuery(useManager().actorWorkerQueryOptions(actorId)); + const enabled = + (features?.includes(ActorFeature.Console) && + !destroyedAt && + !!startedAt) ?? + false; + + const actorQueries = useActor(); + const { data: { rpcs } = {} } = useQuery( + actorQueries.actorRpcsQueryOptions(actorId, { enabled }), + ); + + const [container] = useState( + () => new ActorWorkerContainer(), + ); + + // biome-ignore lint/correctness/useExhaustiveDependencies: we want to create worker on each of those props change + useEffect(() => { + const ctrl = new AbortController(); + + if (enabled) { + container.init({ + actorId, + endpoint, + name, + signal: ctrl.signal, + rpcs, + }); + } + + return () => { + ctrl.abort(); + container.terminate(); + }; + }, [actorId, enabled, rpcs, name, endpoint]); + + return ( + + {children} + + ); +}; + +export function useActorReplCommands() { + const container = useActorWorker(); + return useSyncExternalStore( + useCallback( + (cb) => { + return container.subscribe(cb); + }, + [container], + ), + useCallback(() => { + return container.getCommands(); + }, [container]), + ); +} + +export function useActorWorkerStatus() { + const container = useActorWorker(); + return useSyncExternalStore( + useCallback( + (cb) => { + return container.subscribe(cb); + }, + [container], + ), + useCallback(() => { + return container.getStatus(); + }, [container]), + ); +} diff --git a/frontend/src/components/actors/worker/actor-worker-schema.ts b/frontend/src/components/actors/worker/actor-worker-schema.ts new file mode 100644 index 0000000000..ef1d16d504 --- /dev/null +++ b/frontend/src/components/actors/worker/actor-worker-schema.ts @@ -0,0 +1,74 @@ +import { z } from "zod"; + +export type ReplErrorCode = "unsupported" | "runtime_error" | "syntax"; + +const CodeMessageSchema = z.object({ + type: z.literal("code"), + data: z.string(), + id: z.string(), +}); +const InitMessageSchema = z.object({ + type: z.literal("init"), + rpcs: z.array(z.string()).optional(), + endpoint: z.string(), + name: z.string(), + id: z.string(), +}); + +export const MessageSchema = z.discriminatedUnion("type", [ + CodeMessageSchema, + InitMessageSchema, +]); + +export const FormattedCodeSchema = z + .object({ + fg: z.string().optional(), + tokens: z.array( + z.array( + z.object({ + content: z.string(), + color: z.string().optional(), + }), + ), + ), + }) + .catch((ctx) => ctx.input); + +export const LogSchema = z.object({ + method: z.union([z.literal("log"), z.literal("warn"), z.literal("error")]), + data: z.array(z.any()).optional(), + timestamp: z.string().optional(), +}); + +export const ResponseSchema = z.discriminatedUnion("type", [ + z.object({ + type: z.literal("error"), + id: z.string().optional(), + data: z.any(), + }), + z.object({ + type: z.literal("formatted"), + id: z.string(), + data: FormattedCodeSchema, + }), + z.object({ + type: z.literal("result"), + id: z.string(), + data: z.any().optional(), + }), + z.object({ + type: z.literal("log"), + id: z.string(), + data: LogSchema, + }), + z.object({ + type: z.literal("ready"), + }), +]); + +export type Response = z.infer; +export type Message = z.infer; +export type FormattedCode = z.infer; +export type Log = z.infer; +export type InitMessage = z.infer; +export type CodeMessage = z.infer; diff --git a/frontend/src/components/actors/worker/actor-worker-status.tsx b/frontend/src/components/actors/worker/actor-worker-status.tsx new file mode 100644 index 0000000000..06e5c9c961 --- /dev/null +++ b/frontend/src/components/actors/worker/actor-worker-status.tsx @@ -0,0 +1,41 @@ +import { faExclamationTriangle, faSpinner, Icon } from "@rivet-gg/icons"; +import { AnimatePresence, motion } from "framer-motion"; +import type { ContainerStatus } from "./actor-worker-container"; + +interface ActorWorkerStatusProps { + status: ContainerStatus["type"]; +} + +export function ActorWorkerStatus({ status }: ActorWorkerStatusProps) { + return ( + + {status === "pending" ? ( + + + Connecting to Actor... + + ) : null} + {status === "error" ? ( + + + Couldn't connect to Actor. + + ) : null} + {status === "unsupported" ? ( + + + Console is not supported for this Actor. + + ) : null} + + ); +} diff --git a/frontend/src/components/animated-currency.tsx b/frontend/src/components/animated-currency.tsx new file mode 100644 index 0000000000..85ea938c2c --- /dev/null +++ b/frontend/src/components/animated-currency.tsx @@ -0,0 +1,30 @@ +"use client"; +import { + animate, + domAnimation, + LazyMotion, + motion, + useMotionValue, + useTransform, +} from "framer-motion"; +import { useEffect } from "react"; +import { formatCurrency } from "./lib/formatter"; + +interface AnimatedCurrencyProps { + value: number; +} + +export function AnimatedCurrency({ value }: AnimatedCurrencyProps) { + const startValue = useMotionValue(0); + const currentValue = useTransform(startValue, (v) => formatCurrency(v)); + + useEffect(() => { + animate(startValue, value, { duration: 1, ease: "circIn" }); + }, [startValue, value]); + + return ( + + {currentValue} + + ); +} diff --git a/frontend/src/components/asset-image.tsx b/frontend/src/components/asset-image.tsx new file mode 100644 index 0000000000..0d56b7d58a --- /dev/null +++ b/frontend/src/components/asset-image.tsx @@ -0,0 +1,18 @@ +"use client"; +import { useConfig } from "./lib/config"; + +export function AssetImage( + props: React.DetailedHTMLProps< + React.ImgHTMLAttributes, + HTMLImageElement + >, +) { + const { assetsUrl } = useConfig(); + return ( + {props.alt + ); +} diff --git a/frontend/src/components/code-mirror-container.tsx b/frontend/src/components/code-mirror-container.tsx new file mode 100644 index 0000000000..fb730061d5 --- /dev/null +++ b/frontend/src/components/code-mirror-container.tsx @@ -0,0 +1,15 @@ +import { type ComponentProps, forwardRef } from "react"; +import { cn } from "./lib/utils"; + +export const CodeMirrorContainer = forwardRef< + HTMLDivElement, + ComponentProps<"div"> +>((props, ref) => { + return ( +
+ ); +}); diff --git a/frontend/src/components/code-mirror/index.tsx b/frontend/src/components/code-mirror/index.tsx new file mode 100644 index 0000000000..bdadd2bf68 --- /dev/null +++ b/frontend/src/components/code-mirror/index.tsx @@ -0,0 +1,61 @@ +import { json, jsonParseLinter } from "@codemirror/lang-json"; +import { linter } from "@codemirror/lint"; +import { Annotation } from "@codemirror/state"; +import { githubDark, githubDarkInit } from "@uiw/codemirror-theme-github"; +import ReactCodeMirror, { + type ReactCodeMirrorProps, + type ReactCodeMirrorRef, +} from "@uiw/react-codemirror"; +import { forwardRef } from "react"; + +const theme = githubDarkInit({ + settings: { + background: "transparent", + lineHighlight: "transparent", + fontSize: "12px", + }, +}); + +export const CodeMirror = forwardRef( + (props, ref) => { + return ; + }, +); + +interface JsonCodeProps extends ReactCodeMirrorProps {} + +export const JsonCode = forwardRef( + ({ value, extensions = [], ...props }, ref) => { + return ( + + ); + }, +); + +export const External = Annotation.define(); +export type { CompletionContext } from "@codemirror/autocomplete"; +export { defaultKeymap } from "@codemirror/commands"; +export { javascript, javascriptLanguage } from "@codemirror/lang-javascript"; +export { json, jsonParseLinter } from "@codemirror/lang-json"; +export { EditorView, type KeyBinding, keymap } from "@codemirror/view"; +export type { + ReactCodeMirrorProps as CodeMirrorProps, + ReactCodeMirrorRef as CodeMirrorRef, +} from "@uiw/react-codemirror"; diff --git a/frontend/src/components/code-preview/code-preview.tsx b/frontend/src/components/code-preview/code-preview.tsx new file mode 100644 index 0000000000..5cb00c2f29 --- /dev/null +++ b/frontend/src/components/code-preview/code-preview.tsx @@ -0,0 +1,56 @@ +import { useEffect, useMemo, useRef, useState } from "react"; +import { + createHighlighterCore, + createOnigurumaEngine, + type HighlighterCore, +} from "shiki"; +import { Skeleton } from "../ui/skeleton"; +import theme from "./theme.json"; + +interface CodePreviewProps { + code: string; + language: "typescript"; +} + +export function CodePreview({ code, language }: CodePreviewProps) { + const [isLoading, setIsLoading] = useState(true); + const highlighter = useRef(null); + + useEffect(() => { + if (highlighter.current) return; + + async function createHighlighter() { + highlighter.current ??= await createHighlighterCore({ + themes: [theme], + langs: [import("@shikijs/langs/typescript")], + engine: createOnigurumaEngine(import("shiki/wasm")), + }); + } + + createHighlighter().then(() => { + setIsLoading(false); + }); + }, []); + + const result = useMemo( + () => + isLoading + ? "" + : (highlighter.current?.codeToHtml(code, { + lang: language, + theme: theme.name, + }) as TrustedHTML), + [isLoading, code, language], + ); + + if (isLoading) { + return ; + } + + return ( +
+ ); +} diff --git a/frontend/src/components/code-preview/theme.json b/frontend/src/components/code-preview/theme.json new file mode 100644 index 0000000000..becdfffe9d --- /dev/null +++ b/frontend/src/components/code-preview/theme.json @@ -0,0 +1,788 @@ +{ + "colors": { + "activityBar.activeBorder": "#e6b450b3", + "activityBar.background": "#0c0a09", + "activityBar.border": "#0c0a09", + "activityBar.foreground": "#565b66cc", + "activityBar.inactiveForeground": "#565b6699", + "activityBarBadge.background": "#e6b450", + "activityBarBadge.foreground": "#0c0a09", + "badge.background": "#e6b45033", + "badge.foreground": "#e6b450", + "button.background": "#e6b450", + "button.foreground": "#0c0a09", + "button.hoverBackground": "#e1af4b", + "button.secondaryBackground": "#565b6633", + "button.secondaryForeground": "#bfbdb6", + "button.secondaryHoverBackground": "#565b6680", + "debugConsoleInputIcon.foreground": "#e6b450", + "debugExceptionWidget.background": "#0f131a", + "debugExceptionWidget.border": "#11151c", + "debugIcon.breakpointDisabledForeground": "#f2966880", + "debugIcon.breakpointForeground": "#f29668", + "debugToolBar.background": "#0f131a", + "descriptionForeground": "#565b66", + "diffEditor.diagonalFill": "#11151c", + "diffEditor.insertedTextBackground": "#7fd9621f", + "diffEditor.removedTextBackground": "#f26d781f", + "dropdown.background": "#0d1017", + "dropdown.border": "#565b6645", + "dropdown.foreground": "#565b66", + "editor.background": "#0c0a09", + "editor.findMatchBackground": "#6c5980", + "editor.findMatchBorder": "#6c5980", + "editor.findMatchHighlightBackground": "#6c598066", + "editor.findMatchHighlightBorder": "#5f4c7266", + "editor.findRangeHighlightBackground": "#6c598040", + "editor.foreground": "#bfbdb6", + "editor.inactiveSelectionBackground": "#409fff21", + "editor.lineHighlightBackground": "#131721", + "editor.rangeHighlightBackground": "#6c598033", + "editor.selectionBackground": "#409fff4d", + "editor.selectionHighlightBackground": "#7fd96226", + "editor.selectionHighlightBorder": "#7fd96200", + "editor.snippetTabstopHighlightBackground": "#7fd96233", + "editor.wordHighlightBackground": "#73b8ff14", + "editor.wordHighlightBorder": "#73b8ff80", + "editor.wordHighlightStrongBackground": "#7fd96214", + "editor.wordHighlightStrongBorder": "#7fd96280", + "editorBracketMatch.background": "#6c73804d", + "editorBracketMatch.border": "#6c73804d", + "editorCodeLens.foreground": "#acb6bf8c", + "editorCursor.foreground": "#e6b450", + "editorError.foreground": "#d95757", + "editorGroup.background": "#0f131a", + "editorGroup.border": "#11151c", + "editorGroupHeader.noTabsBackground": "#0c0a09", + "editorGroupHeader.tabsBackground": "#0c0a09", + "editorGroupHeader.tabsBorder": "#0c0a09", + "editorGutter.addedBackground": "#7fd962cc", + "editorGutter.deletedBackground": "#f26d78cc", + "editorGutter.modifiedBackground": "#73b8ffcc", + "editorHoverWidget.background": "#0f131a", + "editorHoverWidget.border": "#11151c", + "editorIndentGuide.activeBackground": "#6c738080", + "editorIndentGuide.background": "#6c738033", + "editorLineNumber.activeForeground": "#6c7380e6", + "editorLineNumber.foreground": "#6c738099", + "editorLink.activeForeground": "#e6b450", + "editorMarkerNavigation.background": "#0f131a", + "editorOverviewRuler.addedForeground": "#7fd962", + "editorOverviewRuler.border": "#11151c", + "editorOverviewRuler.bracketMatchForeground": "#6c7380b3", + "editorOverviewRuler.deletedForeground": "#f26d78", + "editorOverviewRuler.errorForeground": "#d95757", + "editorOverviewRuler.findMatchForeground": "#6c5980", + "editorOverviewRuler.modifiedForeground": "#73b8ff", + "editorOverviewRuler.warningForeground": "#e6b450", + "editorOverviewRuler.wordHighlightForeground": "#73b8ff66", + "editorOverviewRuler.wordHighlightStrongForeground": "#7fd96266", + "editorRuler.foreground": "#6c738033", + "editorSuggestWidget.background": "#0f131a", + "editorSuggestWidget.border": "#11151c", + "editorSuggestWidget.highlightForeground": "#e6b450", + "editorSuggestWidget.selectedBackground": "#47526640", + "editorWarning.foreground": "#e6b450", + "editorWhitespace.foreground": "#6c738099", + "editorWidget.background": "#0f131a", + "editorWidget.border": "#11151c", + "errorForeground": "#d95757", + "extensionButton.prominentBackground": "#e6b450", + "extensionButton.prominentForeground": "#0d1017", + "extensionButton.prominentHoverBackground": "#e1af4b", + "focusBorder": "#e6b450b3", + "foreground": "#565b66", + "gitDecoration.conflictingResourceForeground": "", + "gitDecoration.deletedResourceForeground": "#f26d78b3", + "gitDecoration.ignoredResourceForeground": "#565b6680", + "gitDecoration.modifiedResourceForeground": "#73b8ffb3", + "gitDecoration.submoduleResourceForeground": "#d2a6ffb3", + "gitDecoration.untrackedResourceForeground": "#7fd962b3", + "icon.foreground": "#565b66", + "input.background": "#0d1017", + "input.border": "#565b6645", + "input.foreground": "#bfbdb6", + "input.placeholderForeground": "#565b6680", + "inputOption.activeBackground": "#e6b45033", + "inputOption.activeBorder": "#e6b4504d", + "inputOption.activeForeground": "#e6b450", + "inputValidation.errorBackground": "#0d1017", + "inputValidation.errorBorder": "#d95757", + "inputValidation.infoBackground": "#0c0a09", + "inputValidation.infoBorder": "#39bae6", + "inputValidation.warningBackground": "#0c0a09", + "inputValidation.warningBorder": "#ffb454", + "keybindingLabel.background": "#565b661a", + "keybindingLabel.border": "#bfbdb61a", + "keybindingLabel.bottomBorder": "#bfbdb61a", + "keybindingLabel.foreground": "#bfbdb6", + "list.activeSelectionBackground": "#47526640", + "list.activeSelectionForeground": "#bfbdb6", + "list.deemphasizedForeground": "#d95757", + "list.errorForeground": "#d95757", + "list.filterMatchBackground": "#5f4c7266", + "list.filterMatchBorder": "#6c598066", + "list.focusBackground": "#47526640", + "list.focusForeground": "#bfbdb6", + "list.focusOutline": "#47526640", + "list.highlightForeground": "#e6b450", + "list.hoverBackground": "#47526640", + "list.inactiveSelectionBackground": "#47526633", + "list.inactiveSelectionForeground": "#565b66", + "list.invalidItemForeground": "#565b664d", + "listFilterWidget.background": "#0f131a", + "listFilterWidget.noMatchesOutline": "#d95757", + "listFilterWidget.outline": "#e6b450", + "minimap.background": "#0c0a09", + "minimap.errorHighlight": "#d95757", + "minimap.findMatchHighlight": "#6c5980", + "minimap.selectionHighlight": "#409fff4d", + "minimapGutter.addedBackground": "#7fd962", + "minimapGutter.deletedBackground": "#f26d78", + "minimapGutter.modifiedBackground": "#73b8ff", + "panel.background": "#0c0a09", + "panel.border": "#11151c", + "panelTitle.activeBorder": "#e6b450", + "panelTitle.activeForeground": "#bfbdb6", + "panelTitle.inactiveForeground": "#565b66", + "peekView.border": "#47526640", + "peekViewEditor.background": "#0f131a", + "peekViewEditor.matchHighlightBackground": "#6c598066", + "peekViewEditor.matchHighlightBorder": "#5f4c7266", + "peekViewResult.background": "#0f131a", + "peekViewResult.fileForeground": "#bfbdb6", + "peekViewResult.lineForeground": "#565b66", + "peekViewResult.matchHighlightBackground": "#6c598066", + "peekViewResult.selectionBackground": "#47526640", + "peekViewTitle.background": "#47526640", + "peekViewTitleDescription.foreground": "#565b66", + "peekViewTitleLabel.foreground": "#bfbdb6", + "pickerGroup.border": "#11151c", + "pickerGroup.foreground": "#565b6680", + "progressBar.background": "#e6b450", + "scrollbar.shadow": "#11151c00", + "scrollbarSlider.activeBackground": "#565b66b3", + "scrollbarSlider.background": "#565b6666", + "scrollbarSlider.hoverBackground": "#565b6699", + "selection.background": "#409fff4d", + "settings.headerForeground": "#bfbdb6", + "settings.modifiedItemIndicator": "#73b8ff", + "sideBar.background": "#0c0a09", + "sideBar.border": "#0c0a09", + "sideBarSectionHeader.background": "#0c0a09", + "sideBarSectionHeader.border": "#0c0a09", + "sideBarSectionHeader.foreground": "#565b66", + "sideBarTitle.foreground": "#565b66", + "statusBar.background": "#0c0a09", + "statusBar.border": "#0c0a09", + "statusBar.debuggingBackground": "#f29668", + "statusBar.debuggingForeground": "#0d1017", + "statusBar.foreground": "#565b66", + "statusBar.noFolderBackground": "#0f131a", + "statusBarItem.activeBackground": "#565b6633", + "statusBarItem.hoverBackground": "#565b6633", + "statusBarItem.prominentBackground": "#11151c", + "statusBarItem.prominentHoverBackground": "#00000030", + "statusBarItem.remoteBackground": "#e6b450", + "statusBarItem.remoteForeground": "#0d1017", + "tab.activeBackground": "#0c0a09", + "tab.activeBorder": "#e6b450", + "tab.activeForeground": "#bfbdb6", + "tab.border": "#0c0a09", + "tab.inactiveBackground": "#0c0a09", + "tab.inactiveForeground": "#565b66", + "tab.unfocusedActiveBorder": "#565b66", + "tab.unfocusedActiveForeground": "#565b66", + "tab.unfocusedInactiveForeground": "#565b66", + "terminal.ansiBlack": "#11151c", + "terminal.ansiBlue": "#53bdfa", + "terminal.ansiBrightBlack": "#686868", + "terminal.ansiBrightBlue": "#59c2ff", + "terminal.ansiBrightCyan": "#95e6cb", + "terminal.ansiBrightGreen": "#aad94c", + "terminal.ansiBrightMagenta": "#d2a6ff", + "terminal.ansiBrightRed": "#f07178", + "terminal.ansiBrightWhite": "#ffffff", + "terminal.ansiBrightYellow": "#ffb454", + "terminal.ansiCyan": "#90e1c6", + "terminal.ansiGreen": "#7fd962", + "terminal.ansiMagenta": "#cda1fa", + "terminal.ansiRed": "#ea6c73", + "terminal.ansiWhite": "#c7c7c7", + "terminal.ansiYellow": "#f9af4f", + "terminal.background": "#0c0a09", + "terminal.foreground": "#bfbdb6", + "textBlockQuote.background": "#0f131a", + "textLink.activeForeground": "#e6b450", + "textLink.foreground": "#e6b450", + "textPreformat.foreground": "#bfbdb6", + "titleBar.activeBackground": "#0c0a09", + "titleBar.activeForeground": "#bfbdb6", + "titleBar.border": "#0c0a09", + "titleBar.inactiveBackground": "#0c0a09", + "titleBar.inactiveForeground": "#565b66", + "tree.indentGuidesStroke": "#6c738080", + "walkThrough.embeddedEditorBackground": "#0f131a", + "welcomePage.buttonBackground": "#e6b45066", + "welcomePage.progress.background": "#131721", + "welcomePage.tileBackground": "#0c0a09", + "welcomePage.tileShadow": "#00000080", + "widget.shadow": "#00000080" + }, + "displayName": "Ayu Dark", + "name": "ayu-dark", + "semanticHighlighting": true, + "semanticTokenColors": { + "parameter.label": "#bfbdb6" + }, + "tokenColors": [ + { + "settings": { + "background": "#0c0a09", + "foreground": "#bfbdb6" + } + }, + { + "scope": [ + "comment" + ], + "settings": { + "fontStyle": "italic", + "foreground": "#acb6bf8c" + } + }, + { + "scope": [ + "string", + "constant.other.symbol" + ], + "settings": { + "foreground": "#aad94c" + } + }, + { + "scope": [ + "string.regexp", + "constant.character", + "constant.other" + ], + "settings": { + "foreground": "#95e6cb" + } + }, + { + "scope": [ + "constant.numeric" + ], + "settings": { + "foreground": "#d2a6ff" + } + }, + { + "scope": [ + "constant.language" + ], + "settings": { + "foreground": "#d2a6ff" + } + }, + { + "scope": [ + "variable", + "variable.parameter.function-call" + ], + "settings": { + "foreground": "#bfbdb6" + } + }, + { + "scope": [ + "variable.member" + ], + "settings": { + "foreground": "#f07178" + } + }, + { + "scope": [ + "variable.language" + ], + "settings": { + "fontStyle": "italic", + "foreground": "#39bae6" + } + }, + { + "scope": [ + "storage" + ], + "settings": { + "foreground": "#ff8f40" + } + }, + { + "scope": [ + "keyword" + ], + "settings": { + "foreground": "#ff8f40" + } + }, + { + "scope": [ + "keyword.operator" + ], + "settings": { + "foreground": "#f29668" + } + }, + { + "scope": [ + "punctuation.separator", + "punctuation.terminator" + ], + "settings": { + "foreground": "#bfbdb6b3" + } + }, + { + "scope": [ + "punctuation.section" + ], + "settings": { + "foreground": "#bfbdb6" + } + }, + { + "scope": [ + "punctuation.accessor" + ], + "settings": { + "foreground": "#f29668" + } + }, + { + "scope": [ + "punctuation.definition.template-expression" + ], + "settings": { + "foreground": "#ff8f40" + } + }, + { + "scope": [ + "punctuation.section.embedded" + ], + "settings": { + "foreground": "#ff8f40" + } + }, + { + "scope": [ + "meta.embedded" + ], + "settings": { + "foreground": "#bfbdb6" + } + }, + { + "scope": [ + "source.java storage.type", + "source.haskell storage.type", + "source.c storage.type" + ], + "settings": { + "foreground": "#59c2ff" + } + }, + { + "scope": [ + "entity.other.inherited-class" + ], + "settings": { + "foreground": "#39bae6" + } + }, + { + "scope": [ + "storage.type.function" + ], + "settings": { + "foreground": "#ff8f40" + } + }, + { + "scope": [ + "source.java storage.type.primitive" + ], + "settings": { + "foreground": "#39bae6" + } + }, + { + "scope": [ + "entity.name.function" + ], + "settings": { + "foreground": "#ffb454" + } + }, + { + "scope": [ + "variable.parameter", + "meta.parameter" + ], + "settings": { + "foreground": "#d2a6ff" + } + }, + { + "scope": [ + "variable.function", + "variable.annotation", + "meta.function-call.generic", + "support.function.go" + ], + "settings": { + "foreground": "#ffb454" + } + }, + { + "scope": [ + "support.function", + "support.macro" + ], + "settings": { + "foreground": "#f07178" + } + }, + { + "scope": [ + "entity.name.import", + "entity.name.package" + ], + "settings": { + "foreground": "#aad94c" + } + }, + { + "scope": [ + "entity.name" + ], + "settings": { + "foreground": "#59c2ff" + } + }, + { + "scope": [ + "entity.name.tag", + "meta.tag.sgml" + ], + "settings": { + "foreground": "#39bae6" + } + }, + { + "scope": [ + "support.class.component" + ], + "settings": { + "foreground": "#59c2ff" + } + }, + { + "scope": [ + "punctuation.definition.tag.end", + "punctuation.definition.tag.begin", + "punctuation.definition.tag" + ], + "settings": { + "foreground": "#39bae680" + } + }, + { + "scope": [ + "entity.other.attribute-name" + ], + "settings": { + "foreground": "#ffb454" + } + }, + { + "scope": [ + "support.constant" + ], + "settings": { + "fontStyle": "italic", + "foreground": "#f29668" + } + }, + { + "scope": [ + "support.type", + "support.class", + "source.go storage.type" + ], + "settings": { + "foreground": "#39bae6" + } + }, + { + "scope": [ + "meta.decorator variable.other", + "meta.decorator punctuation.decorator", + "storage.type.annotation" + ], + "settings": { + "foreground": "#e6b673" + } + }, + { + "scope": [ + "invalid" + ], + "settings": { + "foreground": "#d95757" + } + }, + { + "scope": [ + "meta.diff", + "meta.diff.header" + ], + "settings": { + "foreground": "#c594c5" + } + }, + { + "scope": [ + "source.ruby variable.other.readwrite" + ], + "settings": { + "foreground": "#ffb454" + } + }, + { + "scope": [ + "source.css entity.name.tag", + "source.sass entity.name.tag", + "source.scss entity.name.tag", + "source.less entity.name.tag", + "source.stylus entity.name.tag" + ], + "settings": { + "foreground": "#59c2ff" + } + }, + { + "scope": [ + "source.css support.type", + "source.sass support.type", + "source.scss support.type", + "source.less support.type", + "source.stylus support.type" + ], + "settings": { + "foreground": "#acb6bf8c" + } + }, + { + "scope": [ + "support.type.property-name" + ], + "settings": { + "fontStyle": "normal", + "foreground": "#39bae6" + } + }, + { + "scope": [ + "constant.numeric.line-number.find-in-files - match" + ], + "settings": { + "foreground": "#acb6bf8c" + } + }, + { + "scope": [ + "constant.numeric.line-number.match" + ], + "settings": { + "foreground": "#ff8f40" + } + }, + { + "scope": [ + "entity.name.filename.find-in-files" + ], + "settings": { + "foreground": "#aad94c" + } + }, + { + "scope": [ + "message.error" + ], + "settings": { + "foreground": "#d95757" + } + }, + { + "scope": [ + "markup.heading", + "markup.heading entity.name" + ], + "settings": { + "fontStyle": "bold", + "foreground": "#aad94c" + } + }, + { + "scope": [ + "markup.underline.link", + "string.other.link" + ], + "settings": { + "foreground": "#39bae6" + } + }, + { + "scope": [ + "markup.italic" + ], + "settings": { + "fontStyle": "italic", + "foreground": "#f07178" + } + }, + { + "scope": [ + "markup.bold" + ], + "settings": { + "fontStyle": "bold", + "foreground": "#f07178" + } + }, + { + "scope": [ + "markup.italic markup.bold", + "markup.bold markup.italic" + ], + "settings": { + "fontStyle": "bold italic" + } + }, + { + "scope": [ + "markup.raw" + ], + "settings": { + "background": "#bfbdb605" + } + }, + { + "scope": [ + "markup.raw.inline" + ], + "settings": { + "background": "#bfbdb60f" + } + }, + { + "scope": [ + "meta.separator" + ], + "settings": { + "background": "#bfbdb60f", + "fontStyle": "bold", + "foreground": "#acb6bf8c" + } + }, + { + "scope": [ + "markup.quote" + ], + "settings": { + "fontStyle": "italic", + "foreground": "#95e6cb" + } + }, + { + "scope": [ + "markup.list punctuation.definition.list.begin" + ], + "settings": { + "foreground": "#ffb454" + } + }, + { + "scope": [ + "markup.inserted" + ], + "settings": { + "foreground": "#7fd962" + } + }, + { + "scope": [ + "markup.changed" + ], + "settings": { + "foreground": "#73b8ff" + } + }, + { + "scope": [ + "markup.deleted" + ], + "settings": { + "foreground": "#f26d78" + } + }, + { + "scope": [ + "markup.strike" + ], + "settings": { + "foreground": "#e6b673" + } + }, + { + "scope": [ + "markup.table" + ], + "settings": { + "background": "#bfbdb60f", + "foreground": "#39bae6" + } + }, + { + "scope": [ + "text.html.markdown markup.inline.raw" + ], + "settings": { + "foreground": "#f29668" + } + }, + { + "scope": [ + "text.html.markdown meta.dummy.line-break" + ], + "settings": { + "background": "#acb6bf8c", + "foreground": "#acb6bf8c" + } + }, + { + "scope": [ + "punctuation.definition.markdown" + ], + "settings": { + "background": "#bfbdb6", + "foreground": "#acb6bf8c" + } + } + ], + "type": "dark" +} diff --git a/frontend/src/components/code.tsx b/frontend/src/components/code.tsx new file mode 100644 index 0000000000..a793155b10 --- /dev/null +++ b/frontend/src/components/code.tsx @@ -0,0 +1,164 @@ +import { faCopy, faFile, Icon } from "@rivet-gg/icons"; +import { Children, cloneElement, type ReactElement } from "react"; +import { CopyButton } from "./copy-area"; +import { cn } from "./lib/utils"; +import { Badge } from "./ui/badge"; +import { Button } from "./ui/button"; +import { ScrollArea } from "./ui/scroll-area"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "./ui/tabs"; +import { WithTooltip } from "./ui/tooltip"; + +const languageNames = { + csharp: "C#", + cpp: "C++", + go: "Go", + js: "JavaScript", + json: "JSON", + php: "PHP", + python: "Python", + ruby: "Ruby", + ts: "TypeScript", + typescript: "TypeScript", + yaml: "YAML", + gdscript: "GDScript", + powershell: "Command Line", + ps1: "Command Line", + docker: "Docker", + http: "HTTP", + bash: "Command Line", + sh: "Command Line", + prisma: "Prisma", +}; + +interface CodeGroupProps { + className?: string; + children: ReactElement<{ + language?: keyof typeof languageNames; + title?: string; + isInGroup?: boolean; + }>[]; +} + +const getChildIdx = (child: ReactElement) => + child.props?.file || child.props?.title || child.props?.language || "code"; + +export function CodeGroup({ children, className }: CodeGroupProps) { + return ( +
+ + div]:!table" }} + > + + {Children.map(children, (child) => { + const idx = getChildIdx(child); + return ( + + {child.props.title || + languageNames[ + child.props.language || "bash" + ] || + "Code"} + + ); + })} + + + {Children.map(children, (child) => { + const idx = getChildIdx(child); + return ( + + {cloneElement(child, { + isInGroup: true, + ...child.props, + })} + + ); + })} + +
+ ); +} + +interface CodeFrameProps { + file?: string; + title?: string; + language: keyof typeof languageNames; + isInGroup?: boolean; + code?: string; + children?: ReactElement; +} +export const CodeFrame = ({ + children, + file, + language, + code, + title, + isInGroup, +}: CodeFrameProps) => { + return ( +
+
+ + {children + ? cloneElement(children, { escaped: true }) + : null} + +
+ +
+
+ {file ? ( + <> + + {file} + + ) : isInGroup ? null : ( + + {title || languageNames[language]} + + )} +
+ + + + } + content="Copy code" + /> +
+
+ ); +}; + +interface CodeSoruceProps { + children: string; + escaped?: boolean; +} +export const CodeSource = ({ children, escaped }: CodeSoruceProps) => { + if (escaped) { + return ( + + ); + } + return ( + + ); +}; diff --git a/frontend/src/components/connection-form.tsx b/frontend/src/components/connection-form.tsx new file mode 100644 index 0000000000..50cc23be96 --- /dev/null +++ b/frontend/src/components/connection-form.tsx @@ -0,0 +1,68 @@ +import type { ComponentProps } from "react"; +import z from "zod"; +import { + Button, + createSchemaForm, + FormField, + FormItem, + FormLabel, + FormMessage, + Input, +} from "@/components"; + +const connectionFormSchema = z.object({ + username: z + .string() + .url("Please enter a valid URL") + .min(1, "URL is required"), + token: z.string().min(1, "Token is required"), +}); + +const { Form, Submit: ConnectionSubmit } = + createSchemaForm(connectionFormSchema); + +export const ConnectionForm = ( + props: Omit, "children">, +) => { + return ( +
+
+ ( + + Endpoint + + + + )} + /> + ( + + Token + + + + )} + /> +
+ + + +
+
+
+ ); +}; diff --git a/frontend/src/components/copy-area.tsx b/frontend/src/components/copy-area.tsx new file mode 100644 index 0000000000..d0c8af7ffb --- /dev/null +++ b/frontend/src/components/copy-area.tsx @@ -0,0 +1,174 @@ +"use client"; + +import { Slot } from "@radix-ui/react-slot"; +import { faCopy, Icon } from "@rivet-gg/icons"; +import { + type ComponentProps, + forwardRef, + type MouseEventHandler, + type ReactNode, + useState, +} from "react"; +import { toast } from "sonner"; +import { cn } from "./lib/utils"; +import { Button, type ButtonProps } from "./ui/button"; +import { Flex } from "./ui/flex"; +import { Input } from "./ui/input"; +import { WithTooltip } from "./ui/tooltip"; + +interface CopyAreaProps { + className?: string; + value: string; + display?: string; + isConfidential?: boolean; + variant?: "default" | "discrete"; + size?: ButtonProps["size"]; +} + +export const CopyArea = forwardRef( + ( + { + value, + className, + isConfidential, + display, + variant = "default", + ...props + }, + ref, + ) => { + const [isRevealed, setIsRevealed] = useState(false); + const handleClick = () => { + navigator.clipboard.writeText(value); + toast.success("Copied to clipboard"); + }; + + if (variant === "discrete") { + return ( + + ); + } + + return ( + + {isConfidential ? ( + setIsRevealed(true)} + onBlur={() => setIsRevealed(false)} + className="font-mono" + type={isRevealed ? "text" : "password"} + /> + } + /> + ) : ( + + )} + + + + ); + }, +); + +interface CopyButtonProps extends ComponentProps { + children: ReactNode; + value: string | (() => string); +} + +export const CopyButton = forwardRef( + ({ children, value, ...props }, ref) => { + const handleClick: MouseEventHandler = (event) => { + event.stopPropagation(); + event.preventDefault(); + navigator.clipboard.writeText( + typeof value === "function" ? value() : value, + ); + toast.success("Copied to clipboard"); + props.onClick?.(event); + }; + return ( + + {children} + + ); + }, +); + +export type DiscreteCopyButtonProps = CopyButtonProps & + ComponentProps; + +export const DiscreteCopyButton = forwardRef< + HTMLElement, + DiscreteCopyButtonProps +>(({ children, value, ...props }, ref) => { + return ( + + + + } + /> + ); +}); + +interface ClickToCopyProps { + children: ReactNode; + value: string; +} + +export function ClickToCopy({ children, value }: ClickToCopyProps) { + const handleClick = () => { + navigator.clipboard.writeText(value); + toast.success("Copied to clipboard"); + }; + return ( + {children}} + /> + ); +} diff --git a/frontend/src/components/cta-card.tsx b/frontend/src/components/cta-card.tsx new file mode 100644 index 0000000000..6d6df97e8b --- /dev/null +++ b/frontend/src/components/cta-card.tsx @@ -0,0 +1,20 @@ +import { faArrowRight, Icon } from "@rivet-gg/icons"; +import type { PropsWithChildren } from "react"; +import { ActionCard, type ActionCardProps } from "./action-card"; + +export interface CtaCardProps extends Omit {} + +export const CtaCard = (props: CtaCardProps) => { + return ( + } + /> + ); +}; + +export const CardGroup = ({ children }: PropsWithChildren) => { + return ( +
{children}
+ ); +}; diff --git a/frontend/src/components/datepicker.tsx b/frontend/src/components/datepicker.tsx new file mode 100644 index 0000000000..e635ad7d45 --- /dev/null +++ b/frontend/src/components/datepicker.tsx @@ -0,0 +1,155 @@ +"use client"; + +import { faCalendar, Icon } from "@rivet-gg/icons"; +import { format } from "date-fns"; +import type { DateRange } from "react-day-picker"; +import { cn } from "./lib/utils"; +import { Button } from "./ui/button"; +import { Calendar } from "./ui/calendar"; +import { Popover, PopoverContent, PopoverTrigger } from "./ui/popover"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "./ui/select"; + +export type { DateRange }; + +interface DatePickerProps { + date: Date | undefined; + onDateChange: (day: Date | undefined) => void; + className?: string; + presets?: { label: string; date: Date }[]; +} + +export function DatePicker({ + className, + date, + onDateChange, + presets, +}: DatePickerProps) { + return ( + + + + + + {presets ? ( + + ) : null} + + + + ); +} + +interface RangeDatePickerProps { + date: DateRange | undefined; + onDateChange: (range: DateRange | undefined) => void; + className?: string; + presets?: { label: string; date: DateRange }[]; +} + +export function RangeDatePicker({ + date, + className, + onDateChange, + presets, +}: RangeDatePickerProps) { + return ( +
+ + + + + + {presets ? ( + + ) : null} + + + +
+ ); +} diff --git a/frontend/src/components/dialogs/feedback-dialog.tsx b/frontend/src/components/dialogs/feedback-dialog.tsx new file mode 100644 index 0000000000..20197b36d0 --- /dev/null +++ b/frontend/src/components/dialogs/feedback-dialog.tsx @@ -0,0 +1,84 @@ +import { DialogDescription } from "@radix-ui/react-dialog"; +import { faDiscord, Icon } from "@rivet-gg/icons"; +import { usePostHog } from "posthog-js/react"; +import { useState } from "react"; +import * as FeedbackForm from "../forms/feedback-form"; +import type { DialogContentProps } from "../hooks/use-dialog"; +import { FEEDBACK_FORM_ID } from "../lib/constants"; +import { Button } from "../ui/button"; +import { DialogFooter, DialogHeader, DialogTitle } from "../ui/dialog"; +import { Flex } from "../ui/flex"; +import { Link, Text } from "../ui/typography"; + +interface ContentProps extends DialogContentProps { + source?: string; +} + +export default function FeedbackDialogContent({ + onClose, + source = "web", +}: ContentProps) { + const posthog = usePostHog(); + + const [isSubmit, setIsSubmit] = useState(false); + + if (isSubmit) { + return ( + <> + + Feedback sent! + + + All submissions are read by humans, we appreciate your + feedback. + + + + + + ); + } + + return ( + <> + { + posthog.capture("survey sent", { + utm_source: source, + $survey_id: FEEDBACK_FORM_ID, + $survey_response: `${values.type} from ${source}: ${values.feedback}`, + }); + setIsSubmit(true); + }} + defaultValues={{ type: "bug", feedback: "" }} + > + + Feedback + + Join us on{" "} + + Discord + {" "} + to discuss your feedback with the community and the + team. + + + + + + + + + Send + + + + + ); +} diff --git a/frontend/src/components/docs-card.tsx b/frontend/src/components/docs-card.tsx new file mode 100644 index 0000000000..8b00cf5aad --- /dev/null +++ b/frontend/src/components/docs-card.tsx @@ -0,0 +1,7 @@ +import { ExternalCard, type ExternalCardProps } from "./external-card"; + +interface DocsCardProps extends Omit {} + +export const DocsCard = (props: DocsCardProps) => { + return ; +}; diff --git a/frontend/src/components/docs-sheet.tsx b/frontend/src/components/docs-sheet.tsx new file mode 100644 index 0000000000..038aa66679 --- /dev/null +++ b/frontend/src/components/docs-sheet.tsx @@ -0,0 +1,81 @@ +import { faExternalLink, Icon } from "@rivet-gg/icons"; +import type { ReactNode } from "react"; +import { Button } from "./ui/button"; +import { + Sheet, + SheetContent, + SheetDescription, + SheetHeader, + SheetTitle, + SheetTrigger, +} from "./ui/sheet"; +import { WithTooltip } from "./ui/tooltip"; + +interface DocsSheetProps { + path: string; + title: string; + hash?: string; + children?: ReactNode; + showTooltip?: boolean; +} + +export function DocsSheet({ + path, + showTooltip, + title, + children, + hash, +}: DocsSheetProps) { + return ( + + {showTooltip ? ( + {children}} + /> + ) : ( + {children} + )} + + + + {title}{" "} + + + + +
+