diff --git a/docs/installation.md b/docs/installation.md new file mode 100644 index 0000000..7c773ee --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,18 @@ +# Install and Setup + +The Keystone platform includes an official Python client that simplifies integration with the application's REST API. +It handles authentication, request execution, and response parsing, allowing developers to concentrate on application +logic rather than API mechanics. + +The client is published on PyPI and can be installed in the standard fashion. + +```bash +pip install keystone-api-client +``` + +!!! note "Version Compatibility" + + The API client version should match the major and minor version of the upstream API server. + For example, if the API version is `2.3.x`, the compatible client version is `2.3.y`. + Using a mismatched client version may still function, but compatibility is not guaranteed and may + result in inconsistent behavior. diff --git a/docs/logging.md b/docs/logging.md new file mode 100644 index 0000000..f4f6968 --- /dev/null +++ b/docs/logging.md @@ -0,0 +1,58 @@ +# Application Logging + +The Keystone Python client exposes a dedicated logger (`kclient`) that records structured request metadata using the +standard Python logging framework. The logger is registered automatically when the package is imported and can be +configured like any other Python logger. + +## Logger Configuration + +Custom handlers, formatters, and filters may be attached directly to the kclient logger. +Because the logger behaves like any standard Python logger, you can control output destinations, define +message structures, adjust verbosity, and apply filtering based on logged metadata. + +```python +import logging +import keystone_client + +handler = logging.StreamHandler() +handler.setFormatter( + logging.Formatter('%(asctime)s %(levelname)s %(name)s: %(message)s') +) + +logging.getLogger('kclient').addHandler(handler) +``` + +In addition to the standard Python logging attributes, the `kclient` logger includes the following package-specific fields: + +| Field Name | Description | +|------------|----------------------------------------------------------------------------| +| `cid` | Per-session logging id used to correlate requests across a client session. | +| `baseurl` | Base API server URL, including http protocol. | +| `method` | HTTP method for outgoing requests, or an empty string if not applicable. | +| `endpoint` | API endpoint for outgoing requests, or an empty string if not applicable. | +| `url` | Full API URL for outgoing requests, or an empty string if not applicable. | + +## Session IDs + +Each client session is assigned a unique correlation ID (CID) that accompanies all emitted log records. +This identifier provides a reference value for correlating client and API logs across multiple endpoints and requests. +CID values are suitable for inclusion in log messages, passing to downstream services, or correlating requests +for debugging and performance monitoring. + +=== "Synchronous" + + ```python + from keystone_client import KeystoneClient + + with KeystoneClient(url="http://localhost:8000") as client: + print(client.cid) + ``` + +=== "Asynchronous" + + ```python + from keystone_client import AsyncKeystoneClient + + async with AsyncKeystoneClient(url="http://localhost:8000") as aclient: + print(aclient.cid) + ``` diff --git a/docs/index.md b/docs/requests.md similarity index 50% rename from docs/index.md rename to docs/requests.md index f0a3987..9764a4c 100644 --- a/docs/index.md +++ b/docs/requests.md @@ -1,126 +1,8 @@ ---- -hide: - - navigation ---- +# Making API Requests -# Introduction - -Keystone provides a Python client for streamlining interactions with the application's REST API. -The client automates user authentication and data parsing, freeing developers to focus on core application logic. - -## Installation - -The Python client is hosted on PyPI and can be installed in the standard fashion. - -!!! note "Version Compatibility" - - The API client version should match the major and minor version of the upstream API server. - For example, if the API version is `2.3.x`, the compatible client version is `2.3.y`. - Using a mismatched client version may still function, but compatibility is not guaranteed and may - result in inconsistent behavior. - - -```bash -pip install keystone-api-client -``` - -## Instantiating a Client - -The client package provides support for synchronous and asynchronous API calls. -In both cases, requests are pooled across a shared session, reducing HTTP overhead. -The following example instantiates a new session for a locally running server on port `8000`. -Creating the session with a context manager ensures open connections are automatically closed when no longer in use. - -=== "Synchronous" - - ```python - from keystone_client import KeystoneClient - - with KeystoneClient(url="http://localhost:8000") as client: - ... # Your synchronous code here - ``` - -=== "Asynchronous" - - ```python - from keystone_client import AsyncKeystoneClient - - async with AsyncKeystoneClient(url="http://localhost:8000") as aclient: - ... # Your asynchronous code here - ``` - -Sessions can also be opened and closed manually. -This approach is generally discouraged as it increases the likelihood of resource leaks and unclosed connections. - -=== "Synchronous" - - ```python - from keystone_client import KeystoneClient - - client = KeystoneClient(url="http://localhost:8000"): - # Your synchronous code here - client.close() - ``` - -=== "Asynchronous" - - ```python - from keystone_client import AsyncKeystoneClient - - aclient = AsyncKeystoneClient(url="http://localhost:8000"): - # Your asynchronous code here - await aclient.close() - ``` - -Client sessions will automatically manage any relevant session tokens. -This includes assigning a unique correlation ID (CID) used to track requests across Keystone application logs. -CID values are suitable for inclusion in log messages, passing to downstream services, or correlating requests -for debugging and performance monitoring. - -=== "Synchronous" - - ```python - from keystone_client import KeystoneClient - - with KeystoneClient(url="http://localhost:8000") as client: - print(client.cid) - ``` - -=== "Asynchronous" - - ```python - from keystone_client import AsyncKeystoneClient - - async with AsyncKeystoneClient(url="http://localhost:8000") as aclient: - print(aclient.cid) - ``` - -## Authenticating a Session - -The `login` and `logout` methods are used to handle user authentication. -Once authenticated, the client will automatically manage the resulting session tokens. - -=== "Synchronous" - - ```python - from keystone_client import KeystoneClient - - with KeystoneClient(url="http://localhost:8000") as client: - client.login(username="username", password="password") - assert client.is_authenticated() - client.logout() - ``` - -=== "Asynchronous" - - ```python - from keystone_client import AsyncKeystoneClient - - async with AsyncKeystoneClient(url="http://localhost:8000") as aclient: - await aclient.login(username="username", password="password") - assert await aclient.is_authenticated() - await aclient.logout() - ``` +Client classes (`KeystoneClient` and `AsyncKeystoneClient`) provide a high-level interface for interacting the API. +This includes methods for generic HTTP requests in addition to resource-specific CRUD helpers for common workflows. +All requests automatically include any active authentication or session metadata. ## Generic HTTP Requests @@ -137,7 +19,7 @@ Any relevant session/authentication tokens are included automatically when submi Request/response logic is handled using the `httpx` library. API responses are returned as `httpx.Response` objects which encapsulate the response data and status code. -Users are encouraged to familiarize themselves with the `httpx.Response` object and it's methods for parsing response +Users are encouraged to familiarize themselves with the `httpx` library and it's methods for parsing response data and related metadata. A simple example is provided below. @@ -169,7 +51,7 @@ A simple example is provided below. ## CRUD Operations -Dedicated methods are provided for create, retrieve, update, and delete (CRUD) operations for each API resource. +Dedicated methods are provided for create, retrieve, update, and delete (CRUD) operations against each API resource. These methods simplify data manipulation by automatically handling the request and response logic. CRUD methods adhere to the following naming scheme: @@ -291,32 +173,3 @@ The `raise_not_exists` argument can be used to raise an exception instead. ```python await aclient.delete_cluster(pk=1, raise_not_exists=True) ``` - -## Application Logging - -API clients automatically log all requests to the `kclient` log handler. -In addition to the standard default values, `kclient` logs include the application specific values listed below. - -| Field Name | Description | -|------------|----------------------------------------------------------------------------| -| `cid` | Per-session logging id used to correlate requests across a client session. | -| `baseurl` | Base API server URL, including http protocol. | -| `method` | HTTP method for outgoing requests, or an empty string if not applicable. | -| `endpoint` | API endpoint for outgoing requestst, or an empty string if not applicable. | -| `url` | Full API URL for outgoing requests, or an empty string if not applicable. | - -The `kclient` logger is automatically registered when importing the `keystone_client` package. -Formatting, filtering, and persisting log values is left to the user. -For example: - -```python -import logging -import keystone_client - -handler = logging.StreamHandler() -handler.setFormatter( - logging.Formatter('%(cid)s - %(baseurl)s - %(method)s - %(endpoint)s - %(message)s') -) - -logging.getLogger('kclient').addHandler(handler) -``` diff --git a/docs/session.md b/docs/session.md new file mode 100644 index 0000000..960b8ef --- /dev/null +++ b/docs/session.md @@ -0,0 +1,79 @@ +# Starting a Session + +Interacting with the Keystone API begins by creating a client session. +Session objects encapsulate the connection state, authentication details, and request configuration, allowing the +client to efficiently reuse connections and manage resources across multiple API calls. + +## Instantiating a Client + +The client package provides support for synchronous and asynchronous API calls. +The following example instantiates a new session for a locally running server on port `8000`. +Creating the session with a context manager ensures open connections are automatically closed when no longer in use. + +=== "Synchronous" + + ```python + from keystone_client import KeystoneClient + + with KeystoneClient(url="http://localhost:8000") as client: + ... # Your synchronous code here + ``` + +=== "Asynchronous" + + ```python + from keystone_client import AsyncKeystoneClient + + async with AsyncKeystoneClient(url="http://localhost:8000") as aclient: + ... # Your asynchronous code here + ``` + +Sessions can also be opened and closed manually, although this approach is generally discouraged as it increases +the likelihood of resource leaks and unclosed connections. + +=== "Synchronous" + + ```python + from keystone_client import KeystoneClient + + client = KeystoneClient(url="http://localhost:8000"): + # Your synchronous code here + client.close() + ``` + +=== "Asynchronous" + + ```python + from keystone_client import AsyncKeystoneClient + + aclient = AsyncKeystoneClient(url="http://localhost:8000"): + # Your asynchronous code here + await aclient.close() + ``` + +## Authenticating a Session + +The `login` and `logout` methods are used to handle user authentication. +Once authenticated, the client will automatically manage the resulting session tokens. + +=== "Synchronous" + + ```python + from keystone_client import KeystoneClient + + with KeystoneClient(url="http://localhost:8000") as client: + client.login(username="username", password="password") + assert client.is_authenticated() + client.logout() + ``` + +=== "Asynchronous" + + ```python + from keystone_client import AsyncKeystoneClient + + async with AsyncKeystoneClient(url="http://localhost:8000") as aclient: + await aclient.login(username="username", password="password") + assert await aclient.is_authenticated() + await aclient.logout() + ``` diff --git a/mkdocs.yml b/mkdocs.yml index eee1068..272c401 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1 +1,6 @@ site_name: Keystone Python Client +nav: + - installation.md + - session.md + - requests.md + - logging.md