-
Notifications
You must be signed in to change notification settings - Fork 4
6. Client Examples
ChronoLog provides various clients to interact with its system. Each client has been designed to cater to specific use cases, offering users flexibility and ease of use. Below is a description of the available clients and how they can be utilized effectively.
The Client API is a foundational component of ChronoLog that allows developers to interact directly with the system programmatically. This is ideal for scenarios where a user or application needs to:
- Write logs to ChronoLog.
- Perform metadata operations such as creating, acquiring, and releasing Chronicles and Stories.
- Integrate ChronoLog into custom applications with precise control.
- Multi-threaded support for concurrent operations.
- Fine-grained control over ChronoLog functionality.
Below is a simple example that demonstrates the basic use of the ChronoLog Client API without multithreading. This example provides a step-by-step guide to creating a chronicle, acquiring a story, logging events, and cleaning up resources.
#include <chronolog_client.h>
#include <iostream>
#include <cassert>
int main() {
// Configuration file path (update this to your configuration file location)
std::string conf_file_path = "./conf.json";
// Initialize the ChronoLog client
ChronoLog::ConfigurationManager confManager(conf_file_path);
chronolog::Client client(confManager);
// Connect to the ChronoVisor
int ret = client.Connect();
if (ret != chronolog::CL_SUCCESS) {
std::cerr << "Failed to connect to ChronoVisor. Error code: " << ret << std::endl;
return -1;
}
// Define the chronicle and story names
std::string chronicle_name = "example_chronicle";
std::string story_name = "example_story";
// Create a chronicle
std::map<std::string, std::string> chronicle_attrs;
chronicle_attrs.emplace("Priority", "High");
ret = client.CreateChronicle(chronicle_name, chronicle_attrs, 0);
if (ret != chronolog::CL_SUCCESS && ret != chronolog::CL_ERR_CHRONICLE_EXISTS) {
std::cerr << "Failed to create chronicle. Error code: " << ret << std::endl;
return -1;
}
// Acquire a story in the chronicle
std::map<std::string, std::string> story_attrs;
auto acquire_ret = client.AcquireStory(chronicle_name, story_name, story_attrs, 0);
if (acquire_ret.first != chronolog::CL_SUCCESS) {
std::cerr << "Failed to acquire story. Error code: " << acquire_ret.first << std::endl;
return -1;
}
// Log events to the story
auto story_handle = acquire_ret.second;
for (int i = 0; i < 10; ++i) {
story_handle->log_event("Event " + std::to_string(i));
}
// Release the story
ret = client.ReleaseStory(chronicle_name, story_name);
if (ret != chronolog::CL_SUCCESS) {
std::cerr << "Failed to release story. Error code: " << ret << std::endl;
}
// Destroy the story
ret = client.DestroyStory(chronicle_name, story_name);
if (ret != chronolog::CL_SUCCESS) {
std::cerr << "Failed to destroy story. Error code: " << ret << std::endl;
}
// Destroy the chronicle
ret = client.DestroyChronicle(chronicle_name);
if (ret != chronolog::CL_SUCCESS) {
std::cerr << "Failed to destroy chronicle. Error code: " << ret << std::endl;
}
// Disconnect the client
ret = client.Disconnect();
if (ret != chronolog::CL_SUCCESS) {
std::cerr << "Failed to disconnect. Error code: " << ret << std::endl;
}
return 0;
}
For users interested in testing or deploying advanced use cases, the client_lib_multi_storytellers
test demonstrates multi-threaded interactions with ChronoLog. This includes creating chronicles, acquiring and releasing stories, and logging events concurrently across multiple threads.
This test is particularly useful for:
- Evaluating performance under concurrent workloads.
- Simulating real-world scenarios with multiple writers.
The full implementation of client_lib_multi_storytellers
can be found in the ChronoLog repository.
The Interactive Client Admin is a command-line tool that provides an interactive interface for users to manage and operate on ChronoLog deployments. This client is designed for ease of use, allowing real-time interaction with the system.
- Interactive mode activated using the
-i
flag. - Provides a guided interface for managing Chronicles, Stories, and Events.
- Outputs detailed configuration and logging information for troubleshooting and monitoring.
-c <chronicle_name> # Create a Chronicle
-a -s <chronicle_name> <story_name> # Acquire a Story in a Chronicle
-w <event_string> # Write an Event with a payload
-q -s <chronicle_name> <story_name> # Release a Story in a Chronicle
-d -s <chronicle_name> <story_name> # Destroy a Story in a Chronicle
-d -c <chronicle_name> # Destroy a Chronicle
-disconnect # Disconnect from the server
To run the Interactive Client Admin, execute the following command:
client_admin -i
Once launched, the tool will display the list of available commands. You can then enter commands interactively, such as:
-c my_chronicle
-a -s my_chronicle my_story
-w "This is a test event"
-q -s my_chronicle my_story
-d -s my_chronicle my_story
-d -c my_chronicle
-disconnect
The interactive mode is particularly useful for users who are new to ChronoLog or for debugging and monitoring a live system. Error messages and status outputs are displayed after each command to ensure clear feedback.
The Scripted Client Admin extends the functionality of the Interactive Client Admin by enabling automation through scripts. This client is ideal for executing repetitive or predefined tasks without manual intervention.
- Accepts a list of arguments or script files to perform operations.
- Automates the creation, acquisition, and management of Chronicles, Stories, and Events.
- Suitable for running synthetic workloads or batch processing tasks.
Here is an example of a script file (scripted_workload.sh
) to automate operations:
# Create a Chronicle and a Story, write events, and clean up
client_admin -c my_chronicle
client_admin -a -s my_chronicle my_story
client_admin -w "Event 1"
client_admin -w "Event 2"
client_admin -q -s my_chronicle my_story
client_admin -d -s my_chronicle my_story
client_admin -d -c my_chronicle
Execute the script using the -f
flag:
client_admin -f scripted_workload.sh
This example demonstrates how to automate the lifecycle of Chronicles and Stories, making the tool ideal for integration into continuous workflows or stress-testing scenarios.
- Performance Testing: Use the
--perf
flag to collect performance metrics for operations. - Shared Stories: Use the
--shared_story
flag to test collaborative access scenarios.
The Python Client is a wrapper around the Client API, designed to enhance usability and extend ChronoLog’s functionality for a broader range of use cases. This client allows users to interact with ChronoLog using Python, making it accessible to data scientists, researchers, and developers who prefer scripting in Python.
- Simplified API for interacting with ChronoLog.
- Compatible with popular Python libraries for data processing and analysis.
- Ideal for prototyping, data analysis, and integration into Python-based pipelines.
The Python Client is built using the pybind11
library to create Python bindings for the ChronoLog Client API. Below is an example of a Python test script that demonstrates its usage:
import py_chronolog_client
print("Basic test for py_chronolog_client")
# Create ClientPortalServiceConf instance with connection credentials
clientConf = py_chronolog_client.ClientPortalServiceConf("ofi+sockets", "127.0.0.1", 5555, 55)
# Instantiate ChronoLog Client object
client = py_chronolog_client.Client(clientConf)
# Attempt to acquire a story before connecting
attrs = {}
return_tuple = client.AcquireStory("py_chronicle", "my_story", attrs, 1)
print("\nAttempt to acquire story without ChronoVisor connection returns:", return_tuple)
# Connect to ChronoVisor
return_code = client.Connect()
print("\nclient.Connect() call returns:", return_code)
# Create a chronicle
return_code = client.CreateChronicle("py_chronicle", attrs, 1)
print("\nclient.CreateChronicle() returned:", return_code)
# Acquire a story within the chronicle
return_tuple = client.AcquireStory("py_chronicle", "my_story", attrs, 1)
print("\nclient.AcquireStory() returned:", return_tuple)
if return_tuple[0] == 0:
print("\nAcquired Story = my_story within Chronicle = py_chronicle")
# Log events to the story
print("\nLogging events to my_story")
story_handle = return_tuple[1]
story_handle.log_event("py_event")
story_handle.log_event("py_event.2")
story_handle.log_event("py_event.3")
story_handle.log_event("py_event.4")
# Release the story
return_code = client.ReleaseStory("py_chronicle", "my_story")
print("\nclient.ReleaseStory() returned:", return_code)
# Disconnect the client
return_code = client.Disconnect()
print("\nclient.Disconnect() returned:", return_code)
- Build and install ChronoLog, ensuring
py_chronolog_client
is compiled and available in your library directory. - Update environment variables:
- Add the library path to
LD_LIBRARY_PATH
:export LD_LIBRARY_PATH=/path/to/chronolog/lib:$LD_LIBRARY_PATH
- Add the library path to
PYTHONPATH
:export PYTHONPATH=/path/to/chronolog/lib:$PYTHONPATH
- Add the library path to
- Create a symbolic link for the Python client:
ln -s /path/to/chronolog/lib/py_chronolog_client.[python-version-linux-version].so /path/to/chronolog/lib/py_chronolog_client.so
The Python Client enables seamless interaction with ChronoLog, making it highly adaptable for various scenarios such as event logging, data analysis, and workflow integration.
Each client offers unique capabilities tailored to different needs, from direct API access to interactive and automated operations. Choose the client that best suits your workflow, and refer to the provided examples and scripts to get started effectively.