Skip to content

Commit

Permalink
Add support for id counters to metrics addon
Browse files Browse the repository at this point in the history
  • Loading branch information
SanderMertens committed May 18, 2023
1 parent ce03c4f commit 5f8ccee
Show file tree
Hide file tree
Showing 13 changed files with 540 additions and 37 deletions.
170 changes: 157 additions & 13 deletions flecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -22524,12 +22524,15 @@ ECS_COMPONENT_DECLARE(EcsMetricSource);
ECS_TAG_DECLARE(EcsMetric);
ECS_TAG_DECLARE(EcsCounter);
ECS_TAG_DECLARE(EcsCounterIncrement);
ECS_TAG_DECLARE(EcsCounterId);
ECS_TAG_DECLARE(EcsGauge);

/* Internal components */
ECS_COMPONENT_DECLARE(EcsMetricMember);
ECS_COMPONENT_DECLARE(EcsMetricId);
ECS_COMPONENT_DECLARE(EcsMetricOneOf);
ECS_COMPONENT_DECLARE(EcsMetricCountIds);
ECS_COMPONENT_DECLARE(EcsMetricCountTargets);
ECS_COMPONENT_DECLARE(EcsMetricMemberInstance);
ECS_COMPONENT_DECLARE(EcsMetricIdInstance);
ECS_COMPONENT_DECLARE(EcsMetricOneOfInstance);
Expand Down Expand Up @@ -22561,6 +22564,13 @@ typedef struct {
ecs_map_t target_offset; /**< Pair target to metric type offset */
} ecs_oneof_metric_ctx_t;

/** Context for metric that monitors how many entities have a pair target */
typedef struct {
ecs_metric_ctx_t metric;
ecs_id_record_t *idr; /**< Id record for monitored component */
ecs_map_t targets; /**< Map of counters for each target */
} ecs_count_targets_metric_ctx_t;

/** Stores context shared for all instances of member metric */
typedef struct {
ecs_member_metric_ctx_t *ctx;
Expand All @@ -22576,6 +22586,16 @@ typedef struct {
ecs_oneof_metric_ctx_t *ctx;
} EcsMetricOneOf;

/** Stores context shared for all instances of id counter metric */
typedef struct {
ecs_id_t id;
} EcsMetricCountIds;

/** Stores context shared for all instances of target counter metric */
typedef struct {
ecs_count_targets_metric_ctx_t *ctx;
} EcsMetricCountTargets;

/** Instance of member metric */
typedef struct {
ecs_ref_t ref;
Expand Down Expand Up @@ -22626,6 +22646,18 @@ static ECS_MOVE(EcsMetricOneOf, dst, src, {
src->ctx = NULL;
})

static ECS_DTOR(EcsMetricCountTargets, ptr, {
if (ptr->ctx) {
ecs_map_fini(&ptr->ctx->targets);
ecs_os_free(ptr->ctx);
}
})

static ECS_MOVE(EcsMetricCountTargets, dst, src, {
*dst = *src;
src->ctx = NULL;
})

/** Observer used for creating new instances of member metric */
static void flecs_metrics_on_member_metric(ecs_iter_t *it) {
ecs_world_t *world = it->world;
Expand Down Expand Up @@ -22838,6 +22870,49 @@ static void UpdateCounterOneOfInstance(ecs_iter_t *it) {
UpdateOneOfInstance(it, true);
}

static void UpdateCountTargets(ecs_iter_t *it) {
ecs_world_t *world = it->real_world;
EcsMetricCountTargets *m = ecs_field(it, EcsMetricCountTargets, 1);

int32_t i, count = it->count;
for (i = 0; i < count; i ++) {
ecs_count_targets_metric_ctx_t *ctx = m[i].ctx;
ecs_id_record_t *cur = ctx->idr;
while ((cur = cur->first.next)) {
ecs_id_t id = cur->id;
ecs_entity_t *mi = ecs_map_ensure(&ctx->targets, id);
if (!mi[0]) {
mi[0] = ecs_new_w_pair(world, EcsChildOf, ctx->metric.metric);
ecs_entity_t tgt = ecs_pair_second(world, cur->id);
const char *name = ecs_get_name(world, tgt);
if (name) {
ecs_set_name(world, mi[0], name);
}

EcsMetricSource *source = ecs_get_mut(
world, mi[0], EcsMetricSource);
source->entity = tgt;
}

EcsMetricValue *value = ecs_get_mut(world, mi[0], EcsMetricValue);
value->value += (double)ecs_count_id(world, cur->id) *
(double)it->delta_system_time;
}
}
}

static void UpdateCountIds(ecs_iter_t *it) {
ecs_world_t *world = it->real_world;
EcsMetricCountIds *m = ecs_field(it, EcsMetricCountIds, 1);
EcsMetricValue *v = ecs_field(it, EcsMetricValue, 2);

int32_t i, count = it->count;
for (i = 0; i < count; i ++) {
v[i].value += (double)ecs_count_id(world, m[i].id) *
(double)it->delta_system_time;
}
}

/** Initialize member metric */
static
int flecs_member_metric_init(
Expand Down Expand Up @@ -23037,6 +23112,39 @@ int flecs_oneof_metric_init(
return -1;
}

static
int flecs_count_id_targets_metric_init(
ecs_world_t *world,
ecs_entity_t metric,
const ecs_metric_desc_t *desc)
{
ecs_count_targets_metric_ctx_t *ctx = ecs_os_calloc_t(ecs_count_targets_metric_ctx_t);
ctx->metric.metric = metric;
ctx->metric.kind = desc->kind;
ctx->idr = flecs_id_record_ensure(world, desc->id);
ecs_check(ctx->idr != NULL, ECS_INVALID_PARAMETER, NULL);
ecs_map_init(&ctx->targets, NULL);

ecs_set(world, metric, EcsMetricCountTargets, { .ctx = ctx });
ecs_add_pair(world, metric, EcsMetric, desc->kind);
ecs_add_id(world, metric, EcsMetric);

return 0;
error:
return -1;
}

static
int flecs_count_ids_metric_init(
ecs_world_t *world,
ecs_entity_t metric,
const ecs_metric_desc_t *desc)
{
ecs_set(world, metric, EcsMetricCountIds, { .id = desc->id });
ecs_set(world, metric, EcsMetricValue, { .value = 0 });
return 0;
}

ecs_entity_t ecs_metric_init(
ecs_world_t *world,
const ecs_metric_desc_t *desc)
Expand All @@ -23055,8 +23163,12 @@ ecs_entity_t ecs_metric_init(
goto error;
}

if (kind != EcsCounter && kind != EcsGauge && kind != EcsCounterIncrement) {
ecs_err("invalid metric kind");
if (kind != EcsGauge &&
kind != EcsCounter &&
kind != EcsCounterId &&
kind != EcsCounterIncrement)
{
ecs_err("invalid metric kind %s", ecs_get_fullpath(world, kind));
goto error;
}

Expand All @@ -23065,6 +23177,11 @@ ecs_entity_t ecs_metric_init(
goto error;
}

if (kind == EcsCounterId && desc->member) {
ecs_err("CounterIncrement cannot be used in combination with member");
goto error;
}

if (desc->brief) {
#ifdef FLECS_DOC
ecs_doc_set_brief(world, result, desc->brief);
Expand Down Expand Up @@ -23098,20 +23215,32 @@ ecs_entity_t ecs_metric_init(
goto error;
}

ecs_entity_t first = ecs_pair_first(world, desc->id);
ecs_entity_t scope = flecs_get_oneof(world, first);
if (!scope) {
ecs_err("first element of pair must have OneOf with "
" targets enabled");
goto error;
}
if (kind == EcsCounterId) {
if (flecs_count_id_targets_metric_init(world, result, desc)) {
goto error;
}
} else {
ecs_entity_t first = ecs_pair_first(world, desc->id);
ecs_entity_t scope = flecs_get_oneof(world, first);
if (!scope) {
ecs_err("first element of pair must have OneOf with "
" targets enabled");
goto error;
}

if (flecs_oneof_metric_init(world, result, scope, desc)) {
goto error;
if (flecs_oneof_metric_init(world, result, scope, desc)) {
goto error;
}
}
} else {
if (flecs_id_metric_init(world, result, desc)) {
goto error;
if (kind == EcsCounterId) {
if (flecs_count_ids_metric_init(world, result, desc)) {
goto error;
}
} else {
if (flecs_id_metric_init(world, result, desc)) {
goto error;
}
}
}
} else {
Expand Down Expand Up @@ -23139,6 +23268,7 @@ void FlecsMetricsImport(ecs_world_t *world) {
ecs_entity_t old_scope = ecs_set_scope(world, EcsMetric);
ECS_TAG_DEFINE(world, EcsCounter);
ECS_TAG_DEFINE(world, EcsCounterIncrement);
ECS_TAG_DEFINE(world, EcsCounterId);
ECS_TAG_DEFINE(world, EcsGauge);
ecs_set_scope(world, old_scope);

Expand All @@ -23152,6 +23282,8 @@ void FlecsMetricsImport(ecs_world_t *world) {
ECS_COMPONENT_DEFINE(world, EcsMetricMember);
ECS_COMPONENT_DEFINE(world, EcsMetricId);
ECS_COMPONENT_DEFINE(world, EcsMetricOneOf);
ECS_COMPONENT_DEFINE(world, EcsMetricCountIds);
ECS_COMPONENT_DEFINE(world, EcsMetricCountTargets);

ecs_add_id(world, ecs_id(EcsMetricMemberInstance), EcsPrivate);
ecs_add_id(world, ecs_id(EcsMetricIdInstance), EcsPrivate);
Expand Down Expand Up @@ -23189,6 +23321,12 @@ void FlecsMetricsImport(ecs_world_t *world) {
.move = ecs_move(EcsMetricOneOf)
});

ecs_set_hooks(world, EcsMetricCountTargets, {
.ctor = ecs_default_ctor,
.dtor = ecs_dtor(EcsMetricCountTargets),
.move = ecs_move(EcsMetricCountTargets)
});

ecs_add_id(world, EcsMetric, EcsOneOf);

ECS_SYSTEM(world, ClearMetricInstance, EcsPreStore,
Expand Down Expand Up @@ -23228,6 +23366,12 @@ void FlecsMetricsImport(ecs_world_t *world) {
[none] (_, Value),
[in] OneOfInstance,
[none] (Metric, Counter));

ECS_SYSTEM(world, UpdateCountIds, EcsPreStore,
[inout] CountIds, Value);

ECS_SYSTEM(world, UpdateCountTargets, EcsPreStore,
[inout] CountTargets);
}

#endif
Expand Down
18 changes: 15 additions & 3 deletions flecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -11325,6 +11325,9 @@ FLECS_API extern ECS_TAG_DECLARE(EcsCounter);
/** Counter metric that is auto-incremented by source value */
FLECS_API extern ECS_TAG_DECLARE(EcsCounterIncrement);

/** Counter metric that counts the number of entities with an id */
FLECS_API extern ECS_TAG_DECLARE(EcsCounterId);

/** Metric that represents current value */
FLECS_API extern ECS_TAG_DECLARE(EcsGauge);

Expand All @@ -11350,18 +11353,20 @@ typedef struct ecs_metric_desc_t {
ecs_entity_t entity;

/* Entity associated with member that stores metric value. Must not be set
* at the same time as id. */
* at the same time as id. Cannot be combined with EcsCounterId. */
ecs_entity_t member;

/* Tracks whether entities have the specified component id. Must not be set
* at the same time as member. */
ecs_id_t id;

/* If id is a (R, *) wildcard and relationship R has the OneOf property, the
* setting this value to true will track individual targets. */
* setting this value to true will track individual targets.
* If the kind is EcsCountId and the id is a (R, *) wildcard, this value
* will create a metric per target. */
bool targets;

/* Must be either EcsGauge, EcsCounter or EcsCounterIncrement. */
/* Must be EcsGauge, EcsCounter, EcsCounterIncrement or EcsCounterId */
ecs_entity_t kind;

/* Description of metric. Will only be set if FLECS_DOC addon is enabled */
Expand Down Expand Up @@ -17397,6 +17402,7 @@ struct metrics {
struct Metric { };
struct Counter { };
struct CounterIncrement { };
struct CounterId { };
struct Gauge { };

metrics(flecs::world& world);
Expand Down Expand Up @@ -26156,6 +26162,11 @@ struct filter_builder final : _::filter_builder_base<Components...> {
this->m_desc.entity = ecs_entity_init(world, &entity_desc);
}
}

template <typename Func>
void each(Func&& func) {
this->build().each(FLECS_FWD(func));
}
};

}
Expand Down Expand Up @@ -28591,6 +28602,7 @@ inline metrics::metrics(flecs::world& world) {
world.entity<metrics::Instance>("::flecs::metrics::Instance");
world.entity<metrics::Metric>("::flecs::metrics::Metric");
world.entity<metrics::Counter>("::flecs::metrics::Metric::Counter");
world.entity<metrics::CounterId>("::flecs::metrics::Metric::CounterId");
world.entity<metrics::CounterIncrement>("::flecs::metrics::Metric::CounterIncrement");
world.entity<metrics::Gauge>("::flecs::metrics::Metric::Gauge");
}
Expand Down
5 changes: 5 additions & 0 deletions include/flecs/addons/cpp/mixins/filter/builder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ struct filter_builder final : _::filter_builder_base<Components...> {
this->m_desc.entity = ecs_entity_init(world, &entity_desc);
}
}

template <typename Func>
void each(Func&& func) {
this->build().each(FLECS_FWD(func));
}
};

}
1 change: 1 addition & 0 deletions include/flecs/addons/cpp/mixins/metrics/decl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ struct metrics {
struct Metric { };
struct Counter { };
struct CounterIncrement { };
struct CounterId { };
struct Gauge { };

metrics(flecs::world& world);
Expand Down
1 change: 1 addition & 0 deletions include/flecs/addons/cpp/mixins/metrics/impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ inline metrics::metrics(flecs::world& world) {
world.entity<metrics::Instance>("::flecs::metrics::Instance");
world.entity<metrics::Metric>("::flecs::metrics::Metric");
world.entity<metrics::Counter>("::flecs::metrics::Metric::Counter");
world.entity<metrics::CounterId>("::flecs::metrics::Metric::CounterId");
world.entity<metrics::CounterIncrement>("::flecs::metrics::Metric::CounterIncrement");
world.entity<metrics::Gauge>("::flecs::metrics::Metric::Gauge");
}
Expand Down
11 changes: 8 additions & 3 deletions include/flecs/addons/metrics.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ FLECS_API extern ECS_TAG_DECLARE(EcsCounter);
/** Counter metric that is auto-incremented by source value */
FLECS_API extern ECS_TAG_DECLARE(EcsCounterIncrement);

/** Counter metric that counts the number of entities with an id */
FLECS_API extern ECS_TAG_DECLARE(EcsCounterId);

/** Metric that represents current value */
FLECS_API extern ECS_TAG_DECLARE(EcsGauge);

Expand All @@ -72,18 +75,20 @@ typedef struct ecs_metric_desc_t {
ecs_entity_t entity;

/* Entity associated with member that stores metric value. Must not be set
* at the same time as id. */
* at the same time as id. Cannot be combined with EcsCounterId. */
ecs_entity_t member;

/* Tracks whether entities have the specified component id. Must not be set
* at the same time as member. */
ecs_id_t id;

/* If id is a (R, *) wildcard and relationship R has the OneOf property, the
* setting this value to true will track individual targets. */
* setting this value to true will track individual targets.
* If the kind is EcsCountId and the id is a (R, *) wildcard, this value
* will create a metric per target. */
bool targets;

/* Must be either EcsGauge, EcsCounter or EcsCounterIncrement. */
/* Must be EcsGauge, EcsCounter, EcsCounterIncrement or EcsCounterId */
ecs_entity_t kind;

/* Description of metric. Will only be set if FLECS_DOC addon is enabled */
Expand Down
Loading

0 comments on commit 5f8ccee

Please sign in to comment.