Skip to content
Merged

Stat #526

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions include/aws/common/error.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,18 @@
#include <aws/common/assert.h>
#include <aws/common/exports.h>
#include <aws/common/macros.h>
#include <aws/common/package.h>
#include <aws/common/stdint.h>

#define AWS_OP_SUCCESS (0)
#define AWS_OP_ERR (-1)

/* Each library gets space for 2^^10 error entries */
#define AWS_ERROR_ENUM_STRIDE_BITS 10
#define AWS_ERROR_ENUM_STRIDE (1U << AWS_ERROR_ENUM_STRIDE_BITS)
#define AWS_ERROR_ENUM_BEGIN_RANGE(x) ((x)*AWS_ERROR_ENUM_STRIDE)
#define AWS_ERROR_ENUM_END_RANGE(x) (((x) + 1) * AWS_ERROR_ENUM_STRIDE - 1)

struct aws_error_info {
int error_code;
const char *literal_name;
Expand Down Expand Up @@ -144,7 +151,7 @@ int aws_translate_and_raise_io_error(int error_no);
AWS_EXTERN_C_END

enum aws_common_error {
AWS_ERROR_SUCCESS = 0,
AWS_ERROR_SUCCESS = AWS_ERROR_ENUM_BEGIN_RANGE(AWS_C_COMMON_PACKAGE_ID),
AWS_ERROR_OOM,
AWS_ERROR_UNKNOWN,
AWS_ERROR_SHORT_BUFFER,
Expand Down Expand Up @@ -193,7 +200,7 @@ enum aws_common_error {
AWS_ERROR_C_STRING_BUFFER_NOT_NULL_TERMINATED,
AWS_ERROR_STRING_MATCH_NOT_FOUND,

AWS_ERROR_END_COMMON_RANGE = 0x03FF
AWS_ERROR_END_COMMON_RANGE = AWS_ERROR_ENUM_END_RANGE(AWS_C_COMMON_PACKAGE_ID)
};

#endif /* AWS_COMMON_ERROR_H */
12 changes: 7 additions & 5 deletions include/aws/common/logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,11 @@ enum aws_log_level {
*/
typedef uint32_t aws_log_subject_t;

#define AWS_LOG_SUBJECT_BIT_SPACE 10
#define AWS_LOG_SUBJECT_SPACE_SIZE (1 << AWS_LOG_SUBJECT_BIT_SPACE)
#define AWS_LOG_SUBJECT_SPACE_MASK (AWS_LOG_SUBJECT_SPACE_SIZE - 1)
/* Each library gets space for 2^^10 log subject entries */
#define AWS_LOG_SUBJECT_STRIDE_BITS 10
#define AWS_LOG_SUBJECT_STRIDE (1U << AWS_LOG_SUBJECT_STRIDE_BITS)
#define AWS_LOG_SUBJECT_BEGIN_RANGE(x) ((x)*AWS_LOG_SUBJECT_STRIDE)
#define AWS_LOG_SUBJECT_END_RANGE(x) (((x) + 1) * AWS_LOG_SUBJECT_STRIDE - 1)

struct aws_log_subject_info {
aws_log_subject_t subject_id;
Expand All @@ -83,11 +85,11 @@ struct aws_log_subject_info_list {
};

enum aws_common_log_subject {
AWS_LS_COMMON_GENERAL = 0,
AWS_LS_COMMON_GENERAL = AWS_LOG_SUBJECT_BEGIN_RANGE(AWS_C_COMMON_PACKAGE_ID),
AWS_LS_COMMON_TASK_SCHEDULER,
AWS_LS_COMMON_MEMTRACE,

AWS_LS_COMMON_LAST = (AWS_LS_COMMON_GENERAL + AWS_LOG_SUBJECT_SPACE_SIZE - 1)
AWS_LS_COMMON_LAST = AWS_LOG_SUBJECT_END_RANGE(AWS_C_COMMON_PACKAGE_ID)
};

struct aws_logger;
Expand Down
31 changes: 31 additions & 0 deletions include/aws/common/package.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef AWS_COMMON_PACKAGE_H
#define AWS_COMMON_PACKAGE_H

/*
* Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

/*
* Preliminary cap on the number of possible aws-c-libraries participating in shared enum ranges for
* errors, log subjects, and other cross-library enums. Expandable as needed
*/
#define AWS_PACKAGE_SLOTS 16

/*
* Each aws-c-* and aws-crt-* library has a unique package id starting from zero. These are used to macro-calculate
* correct ranges for the cross-library enumerations.
*/
#define AWS_C_COMMON_PACKAGE_ID 0

#endif /* AWS_COMMON_PACKAGE_H */
150 changes: 150 additions & 0 deletions include/aws/common/statistics.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
#ifndef AWS_COMMON_STATISTICS_H
#define AWS_COMMON_STATISTICS_H

/*
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* expressaws_crt_statistics_base or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

#include <aws/common/common.h>
#include <aws/common/package.h>

#include <aws/common/stdint.h>

struct aws_array_list;

typedef uint32_t aws_crt_statistics_category_t;

/* Each library gets space for 2^^8 category entries */
#define AWS_CRT_STATISTICS_CATEGORY_STRIDE_BITS 8
#define AWS_CRT_STATISTICS_CATEGORY_STRIDE (1U << AWS_CRT_STATISTICS_CATEGORY_STRIDE_BITS)
#define AWS_CRT_STATISTICS_CATEGORY_BEGIN_RANGE(x) ((x)*AWS_CRT_STATISTICS_CATEGORY_STRIDE)
#define AWS_CRT_STATISTICS_CATEGORY_END_RANGE(x) (((x) + 1) * AWS_CRT_STATISTICS_CATEGORY_STRIDE - 1)

/**
* The common-specific range of the aws_crt_statistics_category cross-library enum.
*
* This enum functions as an RTTI value that lets statistics handler's interpret (via cast) a
* specific statistics structure if the RTTI value is understood.
*
* Common doesn't have any statistics structures presently, so its range is essentially empty.
*
*/
enum aws_crt_common_statistics_category {
AWSCRT_STAT_CAT_INVALID = AWS_CRT_STATISTICS_CATEGORY_BEGIN_RANGE(AWS_C_COMMON_PACKAGE_ID)
};

/**
* Pattern-struct that functions as a base "class" for all statistics structures. To conform
* to the pattern, a statistics structure must have its first member be the category. In that
* case it becomes "safe" to cast from aws_crt_statistics_base to the specific statistics structure
* based on the category value.
*/
struct aws_crt_statistics_base {
aws_crt_statistics_category_t category;
};

/**
* The start and end time, in milliseconds-since-epoch, that a set of statistics was gathered over.
*/
struct aws_crt_statistics_sample_interval {
uint64_t begin_time_ms;
uint64_t end_time_ms;
};

struct aws_crt_statistics_handler;

/*
* Statistics intake function. The array_list is a list of pointers to aws_crt_statistics_base "derived" (via
* pattern) objects. The handler should iterate the list and downcast elements whose RTTI category it understands,
* while skipping those it does not understand.
*/
typedef void(aws_crt_statistics_handler_process_statistics_fn)(
struct aws_crt_statistics_handler *handler,
struct aws_crt_statistics_sample_interval *interval,
struct aws_array_list *stats,
void *context);

/*
* Destroys a statistics handler implementation
*/
typedef void(aws_crt_statistics_handler_destroy_fn)(struct aws_crt_statistics_handler *handler);

/*
* The period, in milliseconds, that the handler would like to be informed of statistics. Statistics generators are
* not required to honor this value, but should if able.
*/
typedef uint64_t(aws_crt_statistics_handler_get_report_interval_ms_fn)(struct aws_crt_statistics_handler *);

/**
* Vtable for functions that all statistics handlers must implement
*/
struct aws_crt_statistics_handler_vtable {
aws_crt_statistics_handler_process_statistics_fn *process_statistics;
aws_crt_statistics_handler_destroy_fn *destroy;
aws_crt_statistics_handler_get_report_interval_ms_fn *get_report_interval_ms;
};

/**
* Base structure for all statistics handler implementations.
*
* A statistics handler is an object that listens to a stream of polymorphic (via the category RTTI enum) statistics
* structures emitted from some arbitrary source. In the initial implementation, statistics handlers are primarily
* attached to channels, where they monitor IO throughput and state data (from channel handlers) to determine a
* connection's health.
*
* Statistics handlers are a generalization of the timeout and bandwidth filters that are often associated with
* SDK network connections. Configurable, default implementations are defined at the protocol level (http, etc...)
* where they can be attached at connection (channel) creation time.
*/
struct aws_crt_statistics_handler {
struct aws_crt_statistics_handler_vtable *vtable;
struct aws_allocator *allocator;
void *impl;
};

AWS_EXTERN_C_BEGIN

/**
* Submits a list of statistics objects to a statistics handler for processing
*
* handler - the statistics handler that will process the statistics objects
* interval - time period over which the statistics were gathered
* stats - list of pointers to structures that can be case to aws_crt_statistics_base (i.e. have category as a first
* member)
* context - (optional) additional context specific to where the statistics handler has been attached
*/
AWS_COMMON_API
void aws_crt_statistics_handler_process_statistics(
struct aws_crt_statistics_handler *handler,
struct aws_crt_statistics_sample_interval *interval,
struct aws_array_list *stats,
void *context);

/**
* Queries the frequency (via an interval in milliseconds) which a statistics handler would like to be informed
* of statistics.
*/
AWS_COMMON_API
uint64_t aws_crt_statistics_handler_get_report_interval_ms(struct aws_crt_statistics_handler *handler);

/**
* completely destroys a statistics handler. The handler's cleanup function must clean up the impl portion completely
* (including its allocation, if done separately).
*/
AWS_COMMON_API
void aws_crt_statistics_handler_destroy(struct aws_crt_statistics_handler *handler);

AWS_EXTERN_C_END

#endif /* AWS_COMMON_STATISTICS_H */
28 changes: 11 additions & 17 deletions source/error.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,15 @@ static void *s_global_error_context = NULL;
static AWS_THREAD_LOCAL aws_error_handler_fn *tl_thread_handler = NULL;
AWS_THREAD_LOCAL void *tl_thread_handler_context = NULL;

#ifndef AWS_MAX_ERROR_SLOTS
# define AWS_MAX_ERROR_SLOTS 16
#endif

/* Since slot size is 00000100 00000000, to divide, we need to shift right by 10
* bits to find the slot, and to find the modulus, we use a binary and with
* 00000011 11111111 to find the index in that slot. The next three values
* define those constants */
#define AWS_ERROR_SLOT_SIZE 0x0400
#define SLOT_DIV_SHIFT 0x0A
#define SLOT_MASK 0x03FF
* 00000011 11111111 to find the index in that slot.
*/
#define SLOT_MASK (AWS_ERROR_ENUM_STRIDE - 1)

static const int MAX_ERROR_CODE = AWS_ERROR_SLOT_SIZE * AWS_MAX_ERROR_SLOTS;
static const int MAX_ERROR_CODE = AWS_ERROR_ENUM_STRIDE * AWS_PACKAGE_SLOTS;

static const struct aws_error_info_list *volatile ERROR_SLOTS[AWS_MAX_ERROR_SLOTS] = {0};
static const struct aws_error_info_list *volatile ERROR_SLOTS[AWS_PACKAGE_SLOTS] = {0};

int aws_last_error(void) {
return tl_last_error;
Expand All @@ -54,8 +48,8 @@ static const struct aws_error_info *get_error_by_code(int err) {
return NULL;
}

int slot_index = err >> SLOT_DIV_SHIFT;
int error_index = err & SLOT_MASK;
uint32_t slot_index = (uint32_t)err >> AWS_ERROR_ENUM_STRIDE_BITS;
uint32_t error_index = (uint32_t)err & SLOT_MASK;

const struct aws_error_info_list *error_slot = ERROR_SLOTS[slot_index];

Expand Down Expand Up @@ -151,9 +145,9 @@ void aws_register_error_info(const struct aws_error_info_list *error_info) {
AWS_FATAL_ASSERT(error_info->count);

const int min_range = error_info->error_list[0].error_code;
const int slot_index = min_range >> SLOT_DIV_SHIFT;
const int slot_index = min_range >> AWS_ERROR_ENUM_STRIDE_BITS;

if (slot_index >= AWS_MAX_ERROR_SLOTS || slot_index < 0) {
if (slot_index >= AWS_PACKAGE_SLOTS || slot_index < 0) {
/* This is an NDEBUG build apparently. Kill the process rather than
* corrupting heap. */
fprintf(stderr, "Bad error slot index %d\n", slot_index);
Expand Down Expand Up @@ -185,9 +179,9 @@ void aws_unregister_error_info(const struct aws_error_info_list *error_info) {
AWS_FATAL_ASSERT(error_info->count);

const int min_range = error_info->error_list[0].error_code;
const int slot_index = min_range >> SLOT_DIV_SHIFT;
const int slot_index = min_range >> AWS_ERROR_ENUM_STRIDE_BITS;

if (slot_index >= AWS_MAX_ERROR_SLOTS || slot_index < 0) {
if (slot_index >= AWS_PACKAGE_SLOTS || slot_index < 0) {
/* This is an NDEBUG build apparently. Kill the process rather than
* corrupting heap. */
fprintf(stderr, "Bad error slot index %d\n", slot_index);
Expand Down
18 changes: 8 additions & 10 deletions source/logging.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,20 +310,18 @@ int aws_thread_id_t_to_string(aws_thread_id_t thread_id, char *buffer, size_t bu
return AWS_OP_SUCCESS;
}

#ifndef AWS_MAX_LOG_SUBJECT_SLOTS
# define AWS_MAX_LOG_SUBJECT_SLOTS 16u
#endif
#define AWS_LOG_SUBJECT_SPACE_MASK (AWS_LOG_SUBJECT_STRIDE - 1)

static const uint32_t S_MAX_LOG_SUBJECT = AWS_LOG_SUBJECT_SPACE_SIZE * AWS_MAX_LOG_SUBJECT_SLOTS - 1;
static const uint32_t S_MAX_LOG_SUBJECT = AWS_LOG_SUBJECT_STRIDE_BITS * AWS_PACKAGE_SLOTS - 1;

static const struct aws_log_subject_info_list *volatile s_log_subject_slots[AWS_MAX_LOG_SUBJECT_SLOTS] = {0};
static const struct aws_log_subject_info_list *volatile s_log_subject_slots[AWS_PACKAGE_SLOTS] = {0};

static const struct aws_log_subject_info *s_get_log_subject_info_by_id(aws_log_subject_t subject) {
if (subject > S_MAX_LOG_SUBJECT) {
return NULL;
}

uint32_t slot_index = subject >> AWS_LOG_SUBJECT_BIT_SPACE;
uint32_t slot_index = subject >> AWS_LOG_SUBJECT_STRIDE_BITS;
uint32_t subject_index = subject & AWS_LOG_SUBJECT_SPACE_MASK;

const struct aws_log_subject_info_list *subject_slot = s_log_subject_slots[slot_index];
Expand Down Expand Up @@ -356,9 +354,9 @@ void aws_register_log_subject_info_list(struct aws_log_subject_info_list *log_su
AWS_FATAL_ASSERT(log_subject_list->count);

const uint32_t min_range = log_subject_list->subject_list[0].subject_id;
const uint32_t slot_index = min_range >> AWS_LOG_SUBJECT_BIT_SPACE;
const uint32_t slot_index = min_range >> AWS_LOG_SUBJECT_STRIDE_BITS;

if (slot_index >= AWS_MAX_LOG_SUBJECT_SLOTS) {
if (slot_index >= AWS_PACKAGE_SLOTS) {
/* This is an NDEBUG build apparently. Kill the process rather than
* corrupting heap. */
fprintf(stderr, "Bad log subject slot index 0x%016x\n", slot_index);
Expand All @@ -379,9 +377,9 @@ void aws_unregister_log_subject_info_list(struct aws_log_subject_info_list *log_
AWS_FATAL_ASSERT(log_subject_list->count);

const uint32_t min_range = log_subject_list->subject_list[0].subject_id;
const uint32_t slot_index = min_range >> AWS_LOG_SUBJECT_BIT_SPACE;
const uint32_t slot_index = min_range >> AWS_LOG_SUBJECT_STRIDE_BITS;

if (slot_index >= AWS_MAX_LOG_SUBJECT_SLOTS) {
if (slot_index >= AWS_PACKAGE_SLOTS) {
/* This is an NDEBUG build apparently. Kill the process rather than
* corrupting heap. */
fprintf(stderr, "Bad log subject slot index 0x%016x\n", slot_index);
Expand Down
36 changes: 36 additions & 0 deletions source/statistics.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

#include <aws/common/statistics.h>

void aws_crt_statistics_handler_process_statistics(
struct aws_crt_statistics_handler *handler,
struct aws_crt_statistics_sample_interval *interval,
struct aws_array_list *stats,
void *context) {
handler->vtable->process_statistics(handler, interval, stats, context);
}

uint64_t aws_crt_statistics_handler_get_report_interval_ms(struct aws_crt_statistics_handler *handler) {
return handler->vtable->get_report_interval_ms(handler);
}

void aws_crt_statistics_handler_destroy(struct aws_crt_statistics_handler *handler) {
if (handler == NULL) {
return;
}

handler->vtable->destroy(handler);
}