Skip to main content
Version: 2.4.0

Basic Use of the Client API

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.

Key Features

  • Multi-threaded support for concurrent operations.
  • Fine-grained control over ChronoLog functionality.

Example Usage

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;
}

Advanced Example: Multi-Threaded Test Case

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.