Skip to content

File dp_tlm_core.h

File List > dp_tlm > dp_tlm_core.h

Go to the documentation of this file

#ifndef DP_TELEMETRY_H
#define DP_TELEMETRY_H

#include "buffer/buffer.h"
#include "clib_common.h" /* DP_OK, DP_ERR_INVALID */
#include "jm_perf.h"      /* JM_FORCEINLINE */

/* 16-byte ring slots: sizeof(uint64_t)*2 per "complex sample" — exactly one
 * telemetry record each, buying the VM-mirrored contiguity, acquire/release
 * correctness and the dropped counter for free. */
DECLARE_DP_BUFFER (tlmr, uint64_t)


typedef struct
{
  uint64_t n;     
  float    value; 
  uint16_t probe; 
  uint16_t flags; 
} dp_tlm_rec_t;

/* One record must fill exactly one ring slot (C99-portable assert). */
typedef char dp_tlm_rec_fits_slot[sizeof (dp_tlm_rec_t)
                                          == 2 * sizeof (uint64_t)
                                      ? 1
                                      : -1];

#define DP_TLM_REC_DTYPE_JSON                                                 \
  "[[\"n\", \"<u8\"], [\"value\", \"<f4\"], [\"probe\", \"<u2\"], "         \
  "[\"flags\", \"<u2\"]]"

#define DP_TLM_MAX_PROBES 64
#define DP_TLM_NAME_MAX 32

typedef struct
{
  char     name[DP_TLM_NAME_MAX]; 
  uint32_t decim;                 
  uint32_t phase;                 
  uint64_t emitted;               
} dp_tlm_probe_t;

typedef struct dp_tlm_capture dp_tlm_capture_t;

typedef struct dp_tlm
{
  dp_tlmr_t     *ring;    
  uint64_t       now;     
  uint32_t       n_probes;
  dp_tlm_probe_t probes[DP_TLM_MAX_PROBES];
  dp_tlm_capture_t *capture;
  int (*capture_drain) (dp_tlm_capture_t *);
} dp_tlm_t;

typedef dp_tlm_t dp_tlm_state_t;

dp_tlm_t *dp_tlm_create (size_t ring_records);

void dp_tlm_destroy (dp_tlm_t *t);

int dp_tlm_probe (dp_tlm_t *t, const char *name, uint32_t decim);

int dp_tlm_probe_id (const dp_tlm_t *t, const char *name);

int dp_tlm_emit_checked (dp_tlm_t *t, int32_t id, double v);

int dp_tlm_set_decim (dp_tlm_t *t, const char *name, uint32_t decim);

const char *dp_tlm_probe_name (const dp_tlm_t *t, int id);

size_t dp_tlm_probe_count (const dp_tlm_t *t);

size_t dp_tlm_capacity (const dp_tlm_t *t);

int dp_tlm_probe_id_at (const dp_tlm_t *t, size_t i);

size_t dp_tlm_block_bound (const dp_tlm_t *t, size_t block_samples);

size_t dp_tlm_avail (const dp_tlm_t *t);

int dp_tlm_resize (dp_tlm_t *t, size_t records);

typedef struct
{
  uint64_t dropped;  
  uint64_t emitted;  
  size_t   capacity; 
  size_t   probes;   
} dp_tlm_stats_t;

dp_tlm_stats_t dp_tlm_stats (const dp_tlm_t *t);

size_t dp_tlm_read_max_out (dp_tlm_t *t);

size_t dp_tlm_read (dp_tlm_t *t, size_t n, dp_tlm_rec_t *out,
                    size_t max_out);

void dp_tlm_demux_counts (const dp_tlm_rec_t *recs, size_t n, size_t *counts,
                          size_t ncounts);

void dp_tlm_demux (const dp_tlm_rec_t *recs, size_t n, float *const *values,
                   uint64_t *const *index, const size_t *caps, size_t nbuf);

uint64_t dp_tlm_dropped (const dp_tlm_t *t);

uint64_t dp_tlm_emitted (const dp_tlm_t *t, int id);

static inline void
dp_tlm_set_now (dp_tlm_t *t, uint64_t n)
{
  if (!t)
    return;
  if (t->capture_drain)
    t->capture_drain (t->capture);
  t->now = n;
}

JM_FORCEINLINE void
dp_tlm_emit (dp_tlm_t *t, int32_t id, double v)
{
  if (!t || (uint32_t) id >= DP_TLM_MAX_PROBES)
    return;
  dp_tlm_probe_t *p = &t->probes[id];
  if (++p->phase < p->decim)
    return;
  p->phase = 0;
  dp_tlm_rec_t r = { t->now, (float) v, (uint16_t) id, 0u };
  if (dp_tlmr_write (t->ring, (const uint64_t *) &r, 1))
    p->emitted++;
}

#ifndef DP_TLM_DISABLE
#define DP_TLM(ctx, id, v) dp_tlm_emit ((ctx), (id), (v))
#else
#define DP_TLM(ctx, id, v) ((void) 0)
#endif

#endif /* DP_TELEMETRY_H */