Skip to content

CPP-964 Add refresh-interval support for histogram metrics #561

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Oct 23, 2023
Merged

Conversation

absurdfarce
Copy link
Collaborator

Port of Java functionality as defined here.

@absurdfarce
Copy link
Collaborator Author

Some sample code for playing with the refresh rate in a real app:

#include "cassandra.h"
/* Use "#include <dse.h>" when connecting to DataStax Enterpise */
#include <stdio.h>
#include <unistd.h>

void on_log(const CassLogMessage* message, void* data) {
  FILE* log_file = (FILE*)data;
  fprintf(log_file, "%u.%03u [%s] (%s:%d:%s): %s\n", (unsigned int)(message->time_ms / 1000),
          (unsigned int)(message->time_ms % 1000), cass_log_level_string(message->severity),
          message->file, message->line, message->function, message->message);
}

void execute_query(CassStatement* statement, CassSession* session) {

    CassFuture* result_future = cass_session_execute(session, statement);

    if (cass_future_error_code(result_future) == CASS_OK) {
      /* Retrieve result set and get the first row */
      const CassResult* result = cass_future_get_result(result_future);
      const CassRow* row = cass_result_first_row(result);

      if (row) {
        const CassValue* value = cass_row_get_column_by_name(row, "release_version");

        const char* release_version;
        size_t release_version_length;
        cass_value_get_string(value, &release_version, &release_version_length);
        printf("release_version: '%.*s'\n", (int)release_version_length, release_version);
      }

      cass_result_free(result);
    } else {
      /* Handle error */
      const char* message;
      size_t message_length;
      cass_future_error_message(result_future, &message, &message_length);
      fprintf(stderr, "Unable to run query: '%.*s'\n", (int)message_length, message);
    }

    cass_future_free(result_future);
}

int main(int argc, char* argv[]) {

  FILE* log_file = fopen("driver.log", "w+");
  if (log_file == NULL) {
    fprintf(stderr, "Unable to open log file\n");
  }

  /* Log configuration *MUST* be done before any other driver call */
  cass_log_set_level(CASS_LOG_INFO);
  cass_log_set_callback(on_log, (void*)log_file);

  /* Setup and connect to cluster */
  CassFuture* connect_future = NULL;
  CassCluster* cluster = cass_cluster_new();
  CassSession* session = cass_session_new();
  const char* hosts = "127.0.0.1";
  if (argc > 1) {
    hosts = argv[1];
  }
  
  /* Add contact points */
  cass_cluster_set_contact_points(cluster, hosts);

  /* Specify a histogram refresh period */
  cass_cluster_set_histogram_refresh_interval(cluster, 5000);

  /* Provide the cluster object as configuration to connect the session */
  connect_future = cass_session_connect(session, cluster);

  if (cass_future_error_code(connect_future) == CASS_OK) {
    CassFuture* close_future = NULL;

    /* Build statement and execute query */
    const char* query = "SELECT release_version FROM system.local";
    CassStatement* statement = cass_statement_new(query, 0);
    CassMetrics metrics;

    for (int i = 1; i < 10; ++i) {

      execute_query(statement, session);
      sleep(1);

      cass_session_get_metrics(session, &metrics);
      printf("Requests min: %u\n", metrics.requests.min);
    }

    /* Close the session */
    cass_statement_free(statement);
    close_future = cass_session_close(session);
    cass_future_wait(close_future);
    cass_future_free(close_future);
  } else {
    /* Handle error */
    const char* message;
    size_t message_length;
    cass_future_error_message(connect_future, &message, &message_length);
    fprintf(stderr, "Unable to connect: '%.*s'\n", (int)message_length, message);
  }

  cass_future_free(connect_future);
  cass_cluster_free(cluster);
  cass_session_free(session);

  return 0;
}

@@ -142,6 +142,7 @@
#define CASS_DEFAULT_MAX_TRACING_DATA_WAIT_TIME_MS 15
#define CASS_DEFAULT_RETRY_TRACING_DATA_WAIT_TIME_MS 3
#define CASS_DEFAULT_TRACING_CONSISTENCY CASS_CONSISTENCY_ONE
#define CASS_DEFAULT_HISTOGRAM_REFRESH_INTERVAL_NO_REFRESH 0
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love this name for the constant but... I couldn't come up with something I liked better.

: thread_state_(thread_state)
, histograms_(new PerThreadHistogram[thread_state->max_threads()]) {
, histograms_(new PerThreadHistogram[thread_state->max_threads()])
, zero_snapshot_(Snapshot {0,0,0,0,0,0,0,0,0,0}) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like something that should be a static value on the Histogram class but repeated attempts to setup such a value hit various issues that my knowledge of C++ wasn't subtle enough to address. Since we're only creating one of these for a given metrics impl I wasn't too worried about it (the size of a Snapshot shouldn't be a driving concern) but I concede it's not ideal.

}

copy_snapshot(cached_snapshot_, snapshot);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Model here very much is the impl of similar functionality in the 4.x Java driver

src/metrics.hpp Outdated
histograms_[i].add(histogram_);
}

cached_snapshot_ = build_new_snapshot(histogram_);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: can we use build_and_copy_snapshot(histogram_, &cached_snapshot_) here to save an object creation?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not obviously. The whole point of build_and_copy_snapshot() was to avoid the creation of an intermediate Snapshot object and just update the "rv" Snapshot* pointer directly. In this line we very explicitly want to create that intermediate Snapshot object because then we're going to cache it.

Copy link

@joao-r-reis joao-r-reis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a NIT comment, I don't have time to set up an env to build this locally and I see that Henry is already doing that so I'll leave that part to him for now 😅

@absurdfarce
Copy link
Collaborator Author

Hey @hhughes and/or @joao-r-reis ; you guys good after the last round of changes? I think everything has been addressed but wanted a final confirmation from one or (ideally) both of you on that point.

@joao-r-reis
Copy link

Yeah the issue I brought up is resolved.

Copy link
Contributor

@hhughes hhughes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@absurdfarce absurdfarce merged commit fc38817 into master Oct 23, 2023
@absurdfarce absurdfarce deleted the cpp964 branch October 23, 2023 15:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants