Spaces:
Build error
Developer's guide to Qdrant
Build Qdrant
Docker 🐳
Build your own from source
docker build . --tag=qdrant/qdrant
Or use latest pre-built image from DockerHub
docker pull qdrant/qdrant
To run the container, use the command:
docker run -p 6333:6333 qdrant/qdrant
And once you need a fine-grained setup, you can also define a storage path and custom configuration:
docker run -p 6333:6333 \
-v $(pwd)/path/to/data:/qdrant/storage \
-v $(pwd)/path/to/snapshots:/qdrant/snapshots \
-v $(pwd)/path/to/custom_config.yaml:/qdrant/config/production.yaml \
qdrant/qdrant
/qdrant/storage
- is the place where Qdrant persists all your data. Make sure to mount it as a volume, otherwise docker will drop it with the container.
/qdrant/snapshots
- is the place where Qdrant stores snapshots
/qdrant/config/production.yaml
- is the file with engine configuration. You can override any value from the reference config
Now Qdrant should be accessible at localhost:6333.
Local development
Linux/Debian/MacOS
To run Qdrant on local development environment you need to install below:
Install Rust, follow: install rust
Install
rustfmt
toolchain for Rustrustup component add rustfmt
Install dependencies:
sudo apt-get update -y sudo apt-get upgrade -y sudo apt-get install -y curl unzip gcc-multilib \ clang cmake jq \ g++-9-aarch64-linux-gnu \ gcc-9-aarch64-linux-gnu
Install
protoc
from sourcePROTOC_VERSION=22.2 PKG_NAME=$(uname -s | awk '{print ($1 == "Darwin") ? "osx-universal_binary" : (($1 == "Linux") ? "linux-x86_64" : "")}') # curl `proto` source file curl -LO https://github.com/protocolbuffers/protobuf/releases//download/v$PROTOC_VERSION/protoc-$PROTOC_VERSION-$PKG_NAME.zip unzip protoc-$PROTOC_VERSION-$PKG_NAME.zip -d $HOME/.local export PATH="$PATH:$HOME/.local/bin" # remove source file if not needed rm protoc-$PROTOC_VERSION-$PKG_NAME.zip # check installed `protoc` version protoc --version
Build and run the app
cargo build --release --bin qdrant ./target/release/qdrant
Install Python dependencies for testing
poetry -C tests install --sync
Then you could use
poetry -C run pytest tests/openapi
andpoetry -C run pytest tests/consensus_tests
to run the tests.Use the web UI
Web UI repo is in a separate repo, but there's a utility script to sync it to the
static
folder:./tools/sync-web-ui.sh
Nix/NixOS
If you are using Nix package manager (available for Linux and MacOS), you can run nix-shell
in the project root to get a shell with all dependencies installed.
It includes dependencies to build Rust code as well as to run Python tests and various tools in the ./tools
directory.
Profiling
There are several benchmarks implemented in Qdrant. Benchmarks are not included in CI/CD and might take some time to execute. So the expected approach to benchmarking is to run only ones which might be affected by your changes.
To run benchmark, use the following command inside a related sub-crate:
cargo bench --bench name_of_benchmark
In this case you will see the execution timings and, if you launched this bench earlier, the difference in execution time.
Example output:
scoring-vector/basic-score-point
time: [111.81 us 112.07 us 112.31 us]
change: [+19.567% +20.454% +21.404%] (p = 0.00 < 0.05)
Performance has regressed.
Found 9 outliers among 100 measurements (9.00%)
3 (3.00%) low severe
3 (3.00%) low mild
2 (2.00%) high mild
1 (1.00%) high severe
scoring-vector/basic-score-point-10x
time: [111.86 us 112.44 us 113.04 us]
change: [-1.6120% -0.5554% +0.5103%] (p = 0.32 > 0.05)
No change in performance detected.
Found 1 outliers among 100 measurements (1.00%)
1 (1.00%) high mild
FlameGraph and call-graph visualisation
To run benchmarks with profiler to generate FlameGraph - use the following command:
cargo bench --bench name_of_benchmark -- --profile-time=60
This command will run each benchmark iterator for 60
seconds and generate FlameGraph svg along with profiling records files.
These records could later be used to generate visualisation of the call-graph.
Use pprof and the following command to generate svg
with a call graph:
~/go/bin/pprof -output=profile.svg -svg ${qdrant_root}/target/criterion/${benchmark_name}/${function_name}/profile/profile.pb
Real-time profiling
Qdrant have basic tracing
support with Tracy
profiler and tokio-console
integrations
that can be enabled with optional features.
tracing
is an optional dependency that can be enabled withtracing
featuretracy
feature enablesTracy
profiler integrationconsole
feature enablestokio-console
integration- note, that you'll also have to pass
--cfg tokio_unstable
arguments torustc
to enable this feature - by default
tokio-console
binds to127.0.0.1:6669
- if you want to connect
tokio-console
to Qdrant instance running inside a Docker container or on remote server, you can defineTOKIO_CONSOLE_BIND
when running Qdrant to override it (e.g.,TOKIO_CONSOLE_BIND=0.0.0.0:6669
to listen on all interfaces)
- note, that you'll also have to pass
tokio-tracing
feature explicitly enablesTokio
crate tracing- note, that you'll also have to pass
--cfg tokio_unstable
arguments torustc
to enable this feature - this is required (and enabled automatically) by the
console
feature - but you can enable it explicitly with the
tracy
feature, to see Tokio traces inTracy
profiler
- note, that you'll also have to pass
Qdrant code is not instrumented by default, so you'll have to manually add #[tracing::instrument]
attributes
on functions and methods that you want to profile.
Qdrant uses tracing-log
as the log
backend, so log
and log-always
features of the tracing
crate
should not be enabled!
// `tracing` crate is an *optional* dependency in `lib/*` crates, so if you want the code to compile
// when `tracing` feature is disabled, you have to use `#[cfg_attr(...)]`...
//
// See https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute
#[cfg_attr(feature = "tracing", tracing::instrument)]
fn my_function(some_parameter: String) {
// ...
}
// ...or if you just want to do some quick-and-dirty profiling, you can use `#[tracing::instrument]`
// directly, just don't forget to add `--features tracing` when running `cargo` (or add `tracing`
// to default features in `Cargo.toml`)
#[tracing::instrument]
fn some_other_function() {
// ...
}
API changes
REST
Qdrant uses the openapi specification to document its API.
This means changes to the API must be followed by changes to the specification. This is enforced by CI.
Here is a quick step-by-step guide:
- code endpoints and model in Rust
- change specs in
/openapi/*ytt.yaml
- add new schema definitions to
src/schema_generator.rs
- run
./tools/generate_openapi_models.sh
to generate specs - update integration tests
tests/openapi
and run them withpytest tests/openapi
(use poetry or nix to getpytest
) - expose file by starting an HTTP server, for instance
python -m http.server
, in/docs/redoc
- validate specs by browsing redoc on
http://localhost:8000/?v=master
- validate
openapi-merged.yaml
using swagger editor
gRPC
Qdrant uses tonic to serve gRPC traffic.
Our protocol buffers are defined in lib/api/src/grpc/proto/*.proto
- define request and response types using protocol buffers (use oneOf for enums payloads)
- specify RPC methods inside the service definition using protocol buffers
cargo build
will generate the struct definitions and a service trait- implement the service trait in Rust
- start server
cargo run --bin qdrant
- run integration test
./tests/basic_grpc_test.sh
- generate docs
./tools/generate_grpc_docs.sh
Here is a good tonic tutorial for reference.
System integration
On top of the API definitions, Qdrant has a few system integrations that need to be considered when making changes:
- add new endpoints to the metrics allow lists in
src/common/metrics.rs
- test the JWT integration in
tests/auth_tests