summaryrefslogtreecommitdiffstats
path: root/src/fluent-bit/plugins/in_windows_exporter_metrics/we_perflib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fluent-bit/plugins/in_windows_exporter_metrics/we_perflib.c')
-rw-r--r--src/fluent-bit/plugins/in_windows_exporter_metrics/we_perflib.c1048
1 files changed, 1048 insertions, 0 deletions
diff --git a/src/fluent-bit/plugins/in_windows_exporter_metrics/we_perflib.c b/src/fluent-bit/plugins/in_windows_exporter_metrics/we_perflib.c
new file mode 100644
index 000000000..0c140661d
--- /dev/null
+++ b/src/fluent-bit/plugins/in_windows_exporter_metrics/we_perflib.c
@@ -0,0 +1,1048 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2019-2021 The Fluent Bit Authors
+ * Copyright (C) 2015-2018 Treasure Data Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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 <fluent-bit/flb_sds.h>
+
+#include "we.h"
+#include "we_util.h"
+#include "we_metric.h"
+#include "we_perflib.h"
+
+double we_perflib_get_adjusted_counter_value(struct we_perflib_counter *counter)
+{
+ double result;
+
+ result = (double) counter->primary_value.as_qword;
+
+ switch(counter->definition->type) {
+ case PERF_ELAPSED_TIME:
+ result -= counter->parent->parent->time;
+ result /= counter->parent->parent->frequency;
+ break;
+
+ case PERF_100NSEC_TIMER:
+ case PERF_PRECISION_100NS_TIMER:
+ result /= counter->parent->parent->frequency;
+ break;
+ }
+
+ return result;
+}
+
+char *we_perflib_get_counter_type_as_text(uint32_t counter_Type)
+{
+ switch (counter_Type) {
+ case PERF_100NSEC_TIMER:
+ return "PERF_100NSEC_TIMER";
+ case PERF_100NSEC_TIMER_INV:
+ return "PERF_100NSEC_TIMER_INV";
+ case PERF_100NSEC_MULTI_TIMER:
+ return "PERF_100NSEC_MULTI_TIMER";
+ case PERF_100NSEC_MULTI_TIMER_INV:
+ return "PERF_100NSEC_MULTI_TIMER_INV";
+ case PERF_AVERAGE_BASE:
+ return "PERF_AVERAGE_BASE";
+ case PERF_AVERAGE_BULK:
+ return "PERF_AVERAGE_BULK";
+ case PERF_AVERAGE_TIMER:
+ return "PERF_AVERAGE_TIMER";
+ case PERF_COUNTER_100NS_QUEUELEN_TYPE:
+ return "PERF_COUNTER_100NS_QUEUELEN_TYPE";
+ case PERF_COUNTER_BULK_COUNT:
+ return "PERF_COUNTER_BULK_COUNT";
+ case PERF_COUNTER_COUNTER:
+ return "PERF_COUNTER_COUNTER";
+ case PERF_COUNTER_DELTA:
+ return "PERF_COUNTER_DELTA";
+ case PERF_COUNTER_HISTOGRAM_TYPE:
+ return "PERF_COUNTER_HISTOGRAM_TYPE";
+ case PERF_COUNTER_LARGE_DELTA:
+ return "PERF_COUNTER_LARGE_DELTA";
+ case PERF_COUNTER_LARGE_QUEUELEN_TYPE:
+ return "PERF_COUNTER_LARGE_QUEUELEN_TYPE";
+ case PERF_COUNTER_LARGE_RAWCOUNT:
+ return "PERF_COUNTER_LARGE_RAWCOUNT";
+ case PERF_COUNTER_LARGE_RAWCOUNT_HEX:
+ return "PERF_COUNTER_LARGE_RAWCOUNT_HEX";
+ case PERF_COUNTER_MULTI_BASE:
+ return "PERF_COUNTER_MULTI_BASE";
+ case PERF_COUNTER_MULTI_TIMER:
+ return "PERF_COUNTER_MULTI_TIMER";
+ case PERF_COUNTER_MULTI_TIMER_INV:
+ return "PERF_COUNTER_MULTI_TIMER_INV";
+ case PERF_COUNTER_NODATA:
+ return "PERF_COUNTER_NODATA";
+ case PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE:
+ return "PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE";
+ case PERF_COUNTER_QUEUELEN_TYPE:
+ return "PERF_COUNTER_QUEUELEN_TYPE";
+ case PERF_COUNTER_RAWCOUNT:
+ return "PERF_COUNTER_RAWCOUNT";
+ case PERF_COUNTER_RAWCOUNT_HEX:
+ return "PERF_COUNTER_RAWCOUNT_HEX";
+ case PERF_COUNTER_TEXT:
+ return "PERF_COUNTER_TEXT";
+ case PERF_COUNTER_TIMER:
+ return "PERF_COUNTER_TIMER";
+ case PERF_COUNTER_TIMER_INV:
+ return "PERF_COUNTER_TIMER_INV";
+ case PERF_ELAPSED_TIME:
+ return "PERF_ELAPSED_TIME";
+ case PERF_LARGE_RAW_BASE:
+ return "PERF_LARGE_RAW_BASE";
+ case PERF_LARGE_RAW_FRACTION:
+ return "PERF_LARGE_RAW_FRACTION";
+ case PERF_OBJ_TIME_TIMER:
+ return "PERF_OBJ_TIME_TIMER";
+ case PERF_PRECISION_100NS_TIMER:
+ return "PERF_PRECISION_100NS_TIMER";
+ case PERF_PRECISION_OBJECT_TIMER:
+ return "PERF_PRECISION_OBJECT_TIMER";
+ case PERF_PRECISION_SYSTEM_TIMER:
+ return "PERF_PRECISION_SYSTEM_TIMER";
+ case PERF_RAW_BASE:
+ return "PERF_RAW_BASE";
+ case PERF_RAW_FRACTION:
+ return "PERF_RAW_FRACTION";
+ case PERF_SAMPLE_BASE:
+ return "PERF_SAMPLE_BASE";
+ case PERF_SAMPLE_COUNTER:
+ return "PERF_SAMPLE_COUNTER";
+ case PERF_SAMPLE_FRACTION:
+ return "PERF_SAMPLE_FRACTION";
+ };
+
+ return "UNRECOGNIZED_COUNTER_TYPE";
+}
+
+void we_perflib_destroy_counter(struct we_perflib_counter *counter)
+{
+ flb_free(counter);
+}
+
+void we_perflib_destroy_instance(struct we_perflib_instance *instance)
+{
+ struct flb_hash_table_entry *counter_hash_entry;
+ struct mk_list *counter_iterator;
+ struct we_perflib_counter *counter;
+ struct mk_list *tmp;
+
+ mk_list_foreach_safe(counter_iterator,
+ tmp,
+ &instance->counters->entries) {
+ counter_hash_entry = mk_list_entry(counter_iterator,
+ struct flb_hash_table_entry,
+ _head_parent);
+
+ counter = (struct we_perflib_counter *) counter_hash_entry->val;
+
+ we_perflib_destroy_counter(counter);
+ }
+
+ if (instance->name != NULL) {
+ flb_free(instance->name);
+ }
+
+ flb_hash_table_destroy(instance->counters);
+
+ flb_free(instance);
+}
+
+void we_perflib_destroy_counter_definition(
+ struct we_perflib_counter_definition *definition)
+{
+ flb_sds_destroy(definition->name_index_str);
+
+ mk_list_del(&definition->_head);
+
+ flb_free(definition);
+}
+
+void we_perflib_destroy_object(struct we_perflib_object *object)
+{
+ struct mk_list *definition_iterator;
+ struct flb_hash_table_entry *instance_hash_entry;
+ struct mk_list *instance_iterator;
+ struct we_perflib_counter_definition *definition;
+ struct we_perflib_instance *instance;
+ struct mk_list *tmp;
+
+ mk_list_foreach_safe(definition_iterator, tmp, &object->counter_definitions) {
+ definition = mk_list_entry(definition_iterator,
+ struct we_perflib_counter_definition,
+ _head);
+
+ we_perflib_destroy_counter_definition(definition);
+ }
+
+ mk_list_foreach_safe(instance_iterator, tmp, &object->instances->entries) {
+ instance_hash_entry = mk_list_entry(instance_iterator,
+ struct flb_hash_table_entry,
+ _head_parent);
+
+ instance = (struct we_perflib_instance *) instance_hash_entry->val;
+
+ we_perflib_destroy_instance(instance);
+ }
+
+ flb_hash_table_destroy(object->instances);
+
+ flb_free(object);
+}
+
+static int get_string_list(char *source, flb_sds_t *out_result_buffer)
+{
+ DWORD result_buffer_size;
+ flb_sds_t result_buffer;
+ LSTATUS result;
+
+ result_buffer = NULL;
+ result_buffer_size = 0;
+
+ if (out_result_buffer == NULL) {
+ return -1;
+ }
+
+ result = RegQueryValueExA(HKEY_PERFORMANCE_TEXT,
+ source,
+ NULL,
+ NULL,
+ NULL,
+ &result_buffer_size);
+
+ if (result != ERROR_SUCCESS) {
+ return -2;
+ }
+
+ result_buffer = flb_sds_create_size(result_buffer_size);
+
+ if (result_buffer == NULL) {
+ return -3;
+ }
+
+ result = RegQueryValueExA(HKEY_PERFORMANCE_TEXT,
+ source,
+ NULL,
+ NULL,
+ (LPBYTE) result_buffer,
+ &result_buffer_size);
+
+ if (result != ERROR_SUCCESS)
+ {
+ flb_sds_destroy(result_buffer);
+
+ return -4;
+ }
+
+ *out_result_buffer = result_buffer;
+
+ return 0;
+}
+
+static int get_number_of_string_entries(uint32_t *result_count)
+{
+ DWORD argument_size;
+ DWORD entry_count;
+ HKEY key_handle;
+ LSTATUS result;
+
+ entry_count = 0;
+ argument_size = sizeof(DWORD);
+
+ result = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
+ WE_PERFLIB_REGISTRY_PATH,
+ 0,
+ KEY_READ,
+ &key_handle);
+
+ if (result != ERROR_SUCCESS) {
+ return -1;
+ }
+
+ result = RegQueryValueExA(key_handle,
+ WE_PERFLIB_STRING_COUNT_KEY,
+ NULL,
+ 0,
+ (LPBYTE) &entry_count,
+ &argument_size);
+
+ RegCloseKey(key_handle);
+
+ if (result != ERROR_SUCCESS) {
+ return -2;
+ }
+
+ *result_count = (uint32_t) entry_count;
+
+ return 0;
+}
+
+static int get_text_mapping_table(struct flb_hash_table **out_mapping_table)
+{
+ char *current_counter_string;
+ flb_sds_t counter_strings;
+ char *counter_index;
+ char *counter_name;
+ uint32_t string_count;
+ int result;
+
+ if (out_mapping_table == NULL) {
+ return -1;
+ }
+
+ result = get_number_of_string_entries(&string_count);
+
+ if (result) {
+ return -2;
+ }
+
+ result = get_string_list(WE_PERFLIB_COUNTER_KEY_NAME, &counter_strings);
+
+ if (result) {
+ return -3;
+ }
+
+ *out_mapping_table = flb_hash_table_create(FLB_HASH_TABLE_EVICT_NONE,
+ 512, string_count * 2);
+ if (*out_mapping_table == NULL) {
+ flb_sds_destroy(counter_strings);
+
+ return -4;
+ }
+
+ current_counter_string = (char *) counter_strings;
+
+ while (1) {
+ counter_index = current_counter_string;
+ current_counter_string = &current_counter_string[strlen(current_counter_string) + 1];
+
+ if (!current_counter_string[0]) {
+ break;
+ }
+
+ counter_name = current_counter_string;
+ current_counter_string = &current_counter_string[strlen(current_counter_string) + 1];
+
+ if (!current_counter_string[0]) {
+ break;
+ }
+
+ result = flb_hash_table_add(*out_mapping_table,
+ counter_name, strlen(counter_name),
+ counter_index, strlen(counter_index));
+
+ if (result < 0) {
+ flb_sds_destroy(counter_strings);
+ flb_hash_table_destroy(*out_mapping_table);
+
+ *out_mapping_table = NULL;
+
+ return -5;
+ }
+
+ result = flb_hash_table_add(*out_mapping_table,
+ counter_index, strlen(counter_index),
+ counter_name, strlen(counter_name));
+
+ if (result < 0) {
+ flb_sds_destroy(counter_strings);
+ flb_hash_table_destroy(*out_mapping_table);
+
+ *out_mapping_table = NULL;
+
+ return -5;
+ }
+ }
+
+ flb_sds_destroy(counter_strings);
+
+ return 0;
+}
+
+int we_perflib_query_raw_data(struct flb_we *ctx, char *source,
+ char **out_buffer, size_t *out_buffer_size)
+{
+ char *reallocated_buffer;
+ DWORD buffer_size;
+ DWORD data_size;
+ char *buffer;
+ LSTATUS result;
+
+ buffer_size = WE_PERFLIB_QUERY_BUFFER_INITIAL_SIZE;
+
+ result = ERROR_MORE_DATA;
+
+ buffer = (char *) flb_malloc(buffer_size);
+
+ if (buffer == NULL) {
+ return -1;
+ }
+
+ while (result == ERROR_MORE_DATA) {
+ data_size = buffer_size;
+
+ result = RegQueryValueExA(HKEY_PERFORMANCE_DATA,
+ source,
+ NULL,
+ NULL,
+ buffer,
+ &data_size);
+
+ RegCloseKey(HKEY_PERFORMANCE_DATA);
+
+ buffer_size += WE_PERFLIB_QUERY_BUFFER_INCREMENT_SIZE;
+
+ reallocated_buffer = (char *) flb_realloc(buffer, buffer_size);
+
+ if (reallocated_buffer == NULL) {
+ flb_free(buffer);
+
+ return -2;
+ }
+
+ buffer = reallocated_buffer;
+ }
+
+ *out_buffer = buffer;
+ *out_buffer_size = data_size;
+
+ return 0;
+}
+
+static char *we_perflib_lookup_counter_index(struct flb_hash_table *mapping_table,
+ char *name)
+{
+ return flb_hash_table_get_ptr(mapping_table,
+ name,
+ strlen(name));
+}
+
+static char *we_perflib_lookup_counter_name(struct flb_hash_table *mapping_table,
+ uint32_t index)
+{
+ char hash_table_index[11];
+
+ sprintf(hash_table_index, "%" PRIu32, index);
+
+ return flb_hash_table_get_ptr(mapping_table,
+ hash_table_index,
+ strlen(hash_table_index));
+}
+
+static int we_perflib_process_object_type(
+ struct we_perflib_context *context,
+ char *input_data_block,
+ struct we_perflib_object **out_perflib_object)
+{
+ char *input_object_block;
+ struct we_perflib_object *perflib_object;
+ PERF_OBJECT_TYPE *perf_object;
+ PERF_DATA_BLOCK *perf_data;
+ int result;
+
+ perf_data = (PERF_DATA_BLOCK *) input_data_block;
+
+ result = wcsncmp(perf_data->Signature, L"PERF", 4);
+
+ if (result) {
+ return -1;
+ }
+
+ input_object_block = &input_data_block[perf_data->HeaderLength];
+
+ perf_object = (PERF_OBJECT_TYPE *) input_object_block;
+
+ perflib_object = (struct we_perflib_object *) \
+ flb_calloc(1, sizeof(struct we_perflib_object));
+
+ if (perflib_object == NULL) {
+ return -2;
+ }
+
+ perflib_object->name = we_perflib_lookup_counter_name(
+ context->counter_indexes,
+ perf_object->ObjectNameTitleIndex);
+
+ if (perflib_object->name == NULL) {
+ flb_free(perflib_object);
+
+ return -3;
+ }
+
+ perflib_object->time = perf_data->PerfTime.QuadPart;
+ perflib_object->frequency = perf_data->PerfFreq.QuadPart;
+ perflib_object->hundred_ns_time = perf_data->PerfTime100nSec.QuadPart;
+
+ perflib_object->counter_count = perf_object->NumCounters;
+ perflib_object->instance_count = perf_object->NumInstances;
+
+
+ perflib_object->instances = flb_hash_table_create(
+ FLB_HASH_TABLE_EVICT_NONE,
+ 64,
+ perflib_object->instance_count + 1);
+
+ if (perflib_object->instances == NULL) {
+ flb_free(perflib_object);
+
+ return -4;
+ }
+
+ mk_list_init(&perflib_object->counter_definitions);
+
+ *out_perflib_object = perflib_object;
+
+ return perf_data->HeaderLength + perf_object->HeaderLength;
+}
+
+static int we_perflib_process_counter_definition(
+ struct we_perflib_context *context,
+ char *input_data_block,
+ struct we_perflib_counter_definition **out_counter_definition)
+{
+ PERF_COUNTER_DEFINITION *perf_counter_definition;
+ struct we_perflib_counter_definition *counter_definition;
+ char name_index_str[12];
+
+ perf_counter_definition = (PERF_COUNTER_DEFINITION *) input_data_block;
+
+ counter_definition = (struct we_perflib_counter_definition *) \
+ flb_calloc(1, sizeof(struct we_perflib_counter_definition));
+
+ if (counter_definition == NULL) {
+ return -1;
+ }
+
+ counter_definition->name_index = perf_counter_definition->CounterNameTitleIndex;
+
+ counter_definition->name = we_perflib_lookup_counter_name(
+ context->counter_indexes,
+ counter_definition->name_index);
+
+ snprintf(name_index_str,
+ sizeof(name_index_str),
+ "%" PRIu32,
+ counter_definition->name_index);
+
+ counter_definition->name_index_str = flb_sds_create(name_index_str);
+
+ if (counter_definition->name_index_str == NULL) {
+ flb_free(counter_definition);
+
+ return -2;
+ }
+
+ if (counter_definition->name == NULL) {
+ counter_definition->name = "";
+ }
+
+ if (counter_definition->name_index_str == NULL) {
+ counter_definition->name_index_str = flb_sds_create("");
+ }
+
+ counter_definition->help_index = perf_counter_definition->CounterHelpTitleIndex;
+
+ counter_definition->type = perf_counter_definition->CounterType;
+ counter_definition->size = perf_counter_definition->CounterSize;
+ counter_definition->offset = perf_counter_definition->CounterOffset;
+ counter_definition->detail_level = perf_counter_definition->DetailLevel;
+
+ *out_counter_definition = counter_definition;
+
+ return perf_counter_definition->ByteLength;
+}
+
+static int we_perflib_process_counter_definitions(
+ struct we_perflib_context *context,
+ struct we_perflib_object *perflib_object,
+ char *input_data_block)
+{
+ size_t counter_definition_index;
+ struct we_perflib_counter_definition *counter_definition;
+ size_t offset;
+ int result;
+
+ offset = 0;
+
+ for (counter_definition_index = 0 ;
+ counter_definition_index < perflib_object->counter_count ;
+ counter_definition_index++) {
+ result = we_perflib_process_counter_definition(context,
+ &input_data_block[offset],
+ &counter_definition);
+
+ if (result <= 0) {
+ return -1;
+ }
+
+ offset += result;
+
+ mk_list_add(&counter_definition->_head, &perflib_object->counter_definitions);
+ }
+
+ return offset;
+}
+
+static struct we_perflib_counter * we_perflib_create_counter(
+ struct we_perflib_counter_definition *counter_definition)
+{
+ struct we_perflib_counter *counter;
+
+ counter = (struct we_perflib_counter *) \
+ flb_calloc(1, sizeof(struct we_perflib_counter));
+
+ if (counter == NULL) {
+ return NULL;
+ }
+
+ counter->definition = counter_definition;
+
+ return counter;
+}
+
+static int we_perflib_process_counter(
+ struct we_perflib_context *context,
+ struct we_perflib_counter_definition *counter_definition,
+ char *input_data_block,
+ struct we_perflib_counter **out_counter)
+{
+ struct we_perflib_counter *perflib_instance_counter;
+
+ perflib_instance_counter = we_perflib_create_counter(counter_definition);
+
+ if (perflib_instance_counter == NULL) {
+ return -1;
+ }
+
+ memcpy(&perflib_instance_counter->primary_value,
+ &input_data_block[counter_definition->offset],
+ counter_definition->size);
+
+ if (counter_definition->size > sizeof(union we_perflib_value)) {
+ we_perflib_destroy_counter(perflib_instance_counter);
+
+ return -2;
+ }
+
+ *out_counter = perflib_instance_counter;
+
+ return 0;
+}
+
+static int we_perflib_process_counters(struct we_perflib_context *context,
+ struct we_perflib_object *perflib_object,
+ struct we_perflib_instance *instance,
+ char *input_data_block)
+{
+ struct mk_list *counter_definition_iterator;
+ struct we_perflib_counter *perflib_instance_counter;
+ PERF_COUNTER_BLOCK *perf_counter_block;
+ struct we_perflib_counter_definition *counter_definition;
+ int result;
+ int offset;
+
+ perf_counter_block = (PERF_COUNTER_BLOCK *) input_data_block;
+
+ mk_list_foreach(counter_definition_iterator,
+ &perflib_object->counter_definitions) {
+ counter_definition = mk_list_entry(counter_definition_iterator,
+ struct we_perflib_counter_definition,
+ _head);
+
+ if (!counter_definition->name_index) {
+ continue;
+ }
+
+ result = we_perflib_process_counter(context,
+ counter_definition,
+ input_data_block,
+ &perflib_instance_counter);
+
+ if (result < 0) {
+ return -1;
+ }
+
+ perflib_instance_counter->parent = instance;
+
+ result = -1;
+
+ if (counter_definition->name[0]) {
+ result = flb_hash_table_add(instance->counters,
+ counter_definition->name,
+ strlen(counter_definition->name),
+ perflib_instance_counter,
+ 0);
+ }
+ else
+ {
+ result = flb_hash_table_add(instance->counters,
+ counter_definition->name_index_str,
+ strlen(counter_definition->name_index_str),
+ perflib_instance_counter,
+ 0);
+ }
+
+ if (result < 0) {
+ we_perflib_destroy_counter(perflib_instance_counter);
+
+ return -2;
+ }
+ }
+
+ return perf_counter_block->ByteLength;
+}
+
+static struct we_perflib_instance *we_perflib_create_instance(size_t counter_count)
+{
+ struct we_perflib_instance *instance;
+
+ instance = (struct we_perflib_instance *) \
+ flb_calloc(1, sizeof(struct we_perflib_instance));
+
+ if (instance == NULL) {
+ return NULL;
+ }
+
+ instance->counters = flb_hash_table_create(FLB_HASH_TABLE_EVICT_NONE,
+ 64,
+ counter_count + 1);
+
+ if (instance->counters == NULL) {
+ flb_free(instance);
+
+ return NULL;
+ }
+
+ return instance;
+}
+
+static int we_perflib_process_instance(struct we_perflib_context *context,
+ struct we_perflib_object *perflib_object,
+ char *input_data_block,
+ struct we_perflib_instance **out_instance)
+{
+ PERF_INSTANCE_DEFINITION *perf_instance_definition;
+ struct we_perflib_instance *perflib_instance;
+ int offset;
+ int result;
+
+ perflib_instance = we_perflib_create_instance(perflib_object->counter_count);
+
+ if (perflib_instance == NULL) {
+ return -1;
+ }
+
+ offset = 0;
+
+ if (perflib_object->instance_count >= 1) {
+ perf_instance_definition = (PERF_INSTANCE_DEFINITION *) input_data_block;
+
+ if (perf_instance_definition->NameLength > 0) {
+ perflib_instance->name = \
+ we_convert_wstr(&input_data_block[perf_instance_definition->NameOffset], CP_UTF8);
+ if (perflib_instance->name == NULL) {
+ we_perflib_destroy_instance(perflib_instance);
+
+ return -2;
+ }
+ }
+ else {
+ perflib_instance->name = flb_strdup("DEFAULT");
+ }
+
+ offset = perf_instance_definition->ByteLength;
+ }
+
+ perflib_instance->parent = perflib_object;
+
+ result = we_perflib_process_counters(context,
+ perflib_object,
+ perflib_instance,
+ &input_data_block[offset]);
+
+ if (result < 0) {
+ we_perflib_destroy_instance(perflib_instance);
+
+ return -3;
+ }
+
+ offset += result;
+
+ *out_instance = perflib_instance;
+
+ return offset;
+}
+
+static int we_perflib_process_instances(struct we_perflib_context *context,
+ struct we_perflib_object *perflib_object,
+ char *input_data_block)
+{
+ struct we_perflib_instance *perflib_instance;
+ size_t instance_index;
+ int result;
+ int offset;
+
+ offset = 0;
+
+ for (instance_index = 0 ;
+ instance_index < perflib_object->instance_count ;
+ instance_index++) {
+
+ result = we_perflib_process_instance(context,
+ perflib_object,
+ &input_data_block[offset],
+ &perflib_instance);
+
+ if (result <= 0) {
+ return -1;
+ }
+
+ offset += result;
+
+ result = flb_hash_table_add(perflib_object->instances,
+ perflib_instance->name,
+ strlen(perflib_instance->name),
+ perflib_instance,
+ 0);
+
+ if (result < 0) {
+ we_perflib_destroy_instance(perflib_instance);
+
+ return -2;
+ }
+ }
+
+ return offset;
+}
+
+int we_perflib_query(struct flb_we *ctx,
+ char *counter_name,
+ struct we_perflib_object **out_object)
+{
+ char *counter_name_index;
+ char *raw_data_buffer;
+ size_t raw_data_offset;
+ struct we_perflib_object *perflib_object;
+ size_t raw_data_size;
+ int result;
+
+
+ counter_name_index = we_perflib_lookup_counter_index(
+ ctx->perflib_context.counter_indexes, counter_name);
+
+ if (counter_name_index == NULL) {
+ return -1;
+ }
+
+ result = we_perflib_query_raw_data(ctx,
+ counter_name_index,
+ &raw_data_buffer,
+ &raw_data_size);
+
+ if (result) {
+ return -2;
+ }
+
+ raw_data_offset = 0;
+
+ result = we_perflib_process_object_type(&ctx->perflib_context,
+ &raw_data_buffer[raw_data_offset],
+ &perflib_object);
+
+ if (result < 0) {
+ flb_free(raw_data_buffer);
+
+ return -3;
+ }
+
+ raw_data_offset += result;
+
+ result = we_perflib_process_counter_definitions(&ctx->perflib_context,
+ perflib_object,
+ &raw_data_buffer[raw_data_offset]);
+
+ if (result < 0) {
+ we_perflib_destroy_object(perflib_object);
+ flb_free(raw_data_buffer);
+
+ return -4;
+ }
+
+ raw_data_offset += result;
+
+ result = we_perflib_process_instances(&ctx->perflib_context,
+ perflib_object,
+ &raw_data_buffer[raw_data_offset]);
+
+ if (result < 0) {
+ we_perflib_destroy_object(perflib_object);
+ flb_free(raw_data_buffer);
+
+ return -5;
+ }
+
+ flb_free(raw_data_buffer);
+
+ *out_object = perflib_object;
+
+ return 0;
+}
+
+int we_perflib_update_counters(struct flb_we *ctx,
+ char *query,
+ struct we_perflib_metric_source *metric_sources,
+ we_perflib_instance_filter filter_hook,
+ we_perflib_label_prepend_hook label_prepend_hook)
+{
+ char *metric_label_list[WE_PERFLIB_METRIC_LABEL_LIST_SIZE];
+ struct flb_hash_table_entry *instance_hash_entry;
+ size_t metric_label_count;
+ struct mk_list *instance_iterator;
+ struct we_perflib_metric_source *metric_source;
+ size_t metric_index;
+ void *metric_entry;
+ size_t label_index;
+ struct we_perflib_object *measurement;
+ uint64_t timestamp;
+ struct we_perflib_counter *counter;
+ int result;
+
+
+ timestamp = cfl_time_now();
+
+ result = we_perflib_query(ctx, query, &measurement);
+
+ if (result) {
+ return -1;
+ }
+
+ mk_list_foreach_r (instance_iterator, &measurement->instances->entries) {
+ instance_hash_entry = mk_list_entry(instance_iterator,
+ struct flb_hash_table_entry,
+ _head_parent);
+
+ if (filter_hook(instance_hash_entry->key, ctx) == 0) {
+ for (metric_index = 0 ;
+ metric_sources[metric_index].name != NULL ;
+ metric_index++) {
+
+ metric_source = &metric_sources[metric_index];
+
+ counter = we_perflib_get_counter(measurement,
+ instance_hash_entry->key,
+ metric_source->name);
+
+ if (counter == NULL) {
+ return -2;
+ }
+
+ metric_label_count = 0;
+
+ result = label_prepend_hook(metric_label_list,
+ WE_PERFLIB_METRIC_LABEL_LIST_SIZE,
+ &metric_label_count,
+ metric_source,
+ instance_hash_entry->key,
+ counter);
+
+ if (result != 0) {
+ return -3;
+ }
+
+ for (label_index = 0 ;
+ label_index < metric_source->label_set_size;
+ label_index++) {
+ metric_label_list[metric_label_count++] = \
+ metric_source->label_set[label_index];
+ }
+
+ metric_entry = metric_source->parent->metric_instance;
+
+ if (metric_source->parent->type == CMT_COUNTER) {
+ cmt_counter_set(metric_entry, timestamp,
+ we_perflib_get_adjusted_counter_value(counter),
+ metric_label_count, metric_label_list);
+ }
+ else if (metric_source->parent->type == CMT_GAUGE) {
+ cmt_gauge_set(metric_entry, timestamp,
+ we_perflib_get_adjusted_counter_value(counter),
+ metric_label_count, metric_label_list);
+ }
+ }
+ }
+ }
+
+ we_perflib_destroy_object(measurement);
+
+ return 0;
+}
+
+struct we_perflib_counter *we_perflib_get_counter(struct we_perflib_object *object,
+ char *instance_name,
+ char *counter_name)
+{
+ struct we_perflib_instance *instance;
+ struct we_perflib_counter *counter;
+
+ if (instance_name == NULL) {
+ instance_name = "DEFAULT";
+ }
+
+ instance = flb_hash_table_get_ptr(object->instances,
+ instance_name,
+ strlen(instance_name));
+
+ if (instance == NULL) {
+ return NULL;
+ }
+
+ counter = flb_hash_table_get_ptr(instance->counters,
+ counter_name,
+ strlen(counter_name));
+
+ return counter;
+}
+
+int we_perflib_init(struct flb_we *ctx)
+{
+ int result;
+
+ result = get_text_mapping_table(&ctx->perflib_context.counter_indexes);
+
+ if (result) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int we_perflib_exit(struct flb_we *ctx)
+{
+ if (ctx->perflib_context.counter_indexes != NULL) {
+ flb_hash_table_destroy(ctx->perflib_context.counter_indexes);
+ ctx->perflib_context.counter_indexes = NULL;
+ }
+
+ return 0;
+}
+
+/*
+https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc785636(v=ws.10)
+*/
+