|
CX Framework
Cross-platform C utility framework
|
Data Structures | |
| struct | LogWireRecord |
| struct | LogSubSpec |
| struct | LogWireChanInfo |
| One channel in a sender's catalog. More... | |
| struct | LogWireCatalog |
| struct | LogWireGap |
| struct | LogWireFrame |
Typedefs | |
| typedef struct LogWireRecord | LogWireRecord |
| typedef struct LogSubSpec | LogSubSpec |
| typedef struct LogWireChanInfo | LogWireChanInfo |
| One channel in a sender's catalog. | |
| typedef struct LogWireCatalog | LogWireCatalog |
| typedef struct LogWireGap | LogWireGap |
| typedef struct LogWireFrame | LogWireFrame |
| typedef bool(* | LogWireFrameCB) (const LogWireFrame *frame, void *ctx) |
| typedef struct LogWireEncoder | LogWireEncoder |
| Opaque encoder; one per connection. | |
| typedef struct LogWireDecoder | LogWireDecoder |
| Opaque decoder; one per connection. | |
Enumerations | |
| enum | LOG_WIRE_FRAME { LOG_WireSegment = 1 , LOG_WireChanDecl , LOG_WireSiteDecl , LOG_WireEntry , LOG_WireGap , LOG_WireSubscribe , LOG_WireCatalog } |
| enum | LOG_WIRE_FLAGS { LOG_WireOmitCtx = 0x00000001 } |
| Encoder options. More... | |
Functions | |
| LogWireEncoder * | logWireEncoderCreate (strref origin, flags_t flags) |
| void | logWireEncoderDestroy (LogWireEncoder **enc) |
| bool | logWireEncode (LogWireEncoder *enc, Buffer *out, const LogRecord *rec) |
| bool | logWireEncodeGap (LogWireEncoder *enc, Buffer *out, uint64 n, uint64 firstseq, uint64 lastseq) |
| bool | logWireEncodeSub (LogWireEncoder *enc, Buffer *out, const LogSubSpec *spec) |
| bool | logWireEncodeCatalog (LogWireEncoder *enc, Buffer *out, _In_reads_(nchans) const LogWireChanInfo *chans, int nchans) |
| void | logWireEndSegment (LogWireEncoder *enc) |
| LogWireDecoder * | logWireDecoderCreate (void) |
| void | logWireDecoderDestroy (LogWireDecoder **dec) |
| bool | logWireDecode (LogWireDecoder *dec, const uint8 *buf, size_t len, LogWireFrameCB cb, void *ctx) |
| bool | logInject (strref chanpath, const LogWireRecord *rec) |
Turns a LogRecord into bytes that another cx instance can turn back into a LogRecord.
cx never touches a wire. There is no listening, connecting, reading, writing or authenticating anywhere in the log system. This codec produces complete frames and hands them to whoever asked for them; the application decides what a connection is, and may multiplex log traffic into a stream it already has, wrap it in its own authentication, or carry it over something that is not a socket at all. See Forwarding for the destination that drives this codec, and logInject() for the receiving end.
A frame is a kind, a length, and a payload. Frames arrive in order and a decoder hands each one to a callback as it completes, so a transport may deliver bytes in any sized pieces.
Frames are grouped into segments. A segment is one self-contained document: everything a frame refers to – channel paths, message templates, field names – is declared once within the segment that uses it, so a busy channel costs its path exactly once no matter how many records name it. A new segment starts whenever the encoder is told to end the current one, which is what makes a stored run of frames safe to trim from the front: whole segments can be dropped and the rest still decodes.
Every encode call writes its frames into a Buffer, replacing whatever was in it. Hand the same Buffer back on the next call and it is reused, growing only when a run of frames needs more room than it already has. Destroy it with bufDestroy() when you are done with it.
| typedef struct LogSubSpec LogSubSpec |
What a receiver has asked a sender for
A sender ships nothing until one of these arrives; there is no locally configured "forward everything to host X". See Forwarding.
| typedef struct LogWireCatalog LogWireCatalog |
What a sender is capable of logging
The channel inventory, which is what an operator browses before deciding what to subscribe to. Call sites are not in it: C offers no portable way to enumerate the statics in a binary, so what a channel actually says only becomes visible once something logs to it.
| typedef struct LogWireFrame LogWireFrame |
One decoded frame
Only the member matching kind is filled in; the rest are NULL.
| typedef bool(* LogWireFrameCB) (const LogWireFrame *frame, void *ctx) |
Called once per complete frame
| frame | The frame; valid only for the duration of the call |
| ctx | User context passed to logWireDecode() |
| typedef struct LogWireGap LogWireGap |
Records a sender dropped instead of sending
A gap says how much is missing and where, so a receiver can say so rather than silently showing a shorter log than the sender produced.
| typedef struct LogWireRecord LogWireRecord |
One decoded log record, as it came off the wire
Everything here is borrowed for the duration of the frame callback. Hand it to logInject() to deliver it locally, or copy what you need.
| enum LOG_WIRE_FLAGS |
| enum LOG_WIRE_FRAME |
Kinds of frame that can appear on the wire
A decoder hands a frame kind it does not implement to the callback with nothing filled in, rather than failing, so an older receiver keeps working against a newer sender.
| bool logInject | ( | strref | chanpath, |
| const LogWireRecord * | rec | ||
| ) |
Deliver a record that came from another instance to this one's destinations
The record goes through the same routing, filtering and per-channel level checks as anything logged here, so a record that does not arrive was dropped for a reason a local record would have been dropped for too. Its timestamp, sequence number and batch id are the sender's and are not replaced.
| chanpath | Channel to deliver it to, interned locally if it is new |
| rec | Record decoded from the wire |
| bool logWireDecode | ( | LogWireDecoder * | dec, |
| const uint8 * | buf, | ||
| size_t | len, | ||
| LogWireFrameCB | cb, | ||
| void * | ctx | ||
| ) |
Feed received bytes to a decoder
Every frame that completes is handed to cb. A frame that is only partly here is kept until the rest of it arrives, so bytes may be fed in any sized pieces.
| dec | Decoder to feed |
| buf | Bytes received |
| len | Number of bytes |
| cb | Called once per complete frame |
| ctx | Passed to the callback |
| LogWireDecoder * logWireDecoderCreate | ( | void | ) |
Create a decoder
| void logWireDecoderDestroy | ( | LogWireDecoder ** | dec | ) |
Destroy a decoder
| dec | Pointer to the decoder handle; set to NULL |
| bool logWireEncode | ( | LogWireEncoder * | enc, |
| Buffer * | out, | ||
| const LogRecord * | rec | ||
| ) |
Encode one record
Writes one or more complete frames into out: whatever declarations this record needs and has not sent yet, then the record itself. Nothing partial is ever written.
| enc | Encoder to use |
| out | Receives the frames, replacing anything already in the buffer. A NULL buffer is created; an existing one is reused and grown as needed. |
| rec | Record to encode |
out is left empty in that case | bool logWireEncodeCatalog | ( | LogWireEncoder * | enc, |
| Buffer * | out, | ||
| _In_reads_(nchans) const LogWireChanInfo * | chans, | ||
| int | nchans | ||
| ) |
Encode a channel catalog
| enc | Encoder to use |
| out | Receives the frame, replacing anything already in the buffer |
| chans | Channels to describe |
| nchans | Number of channels |
| bool logWireEncodeGap | ( | LogWireEncoder * | enc, |
| Buffer * | out, | ||
| uint64 | n, | ||
| uint64 | firstseq, | ||
| uint64 | lastseq | ||
| ) |
Encode a gap
| enc | Encoder to use |
| out | Receives the frame, replacing anything already in the buffer |
| n | How many records were dropped |
| firstseq | Sequence number of the first one |
| lastseq | Sequence number of the last one |
| LogWireEncoder * logWireEncoderCreate | ( | strref | origin, |
| flags_t | flags | ||
| ) |
Create an encoder
| origin | This instance's identity, stamped on every record that does not already carry one. Empty leaves records unstamped. |
| flags | LOG_WIRE_FLAGS options, or 0 |
| void logWireEncoderDestroy | ( | LogWireEncoder ** | enc | ) |
Destroy an encoder
| enc | Pointer to the encoder handle; set to NULL |
| bool logWireEncodeSub | ( | LogWireEncoder * | enc, |
| Buffer * | out, | ||
| const LogSubSpec * | spec | ||
| ) |
Encode a subscription request
For the receiving side of a connection: this is what a collector sends to a sender to say what it wants. Sending it needs an encoder of its own, since the control plane is the same framing running the other way.
| enc | Encoder to use |
| out | Receives the frame, replacing anything already in the buffer |
| spec | What is being asked for; NULL cancels an existing subscription |
| void logWireEndSegment | ( | LogWireEncoder * | enc | ) |
End the current segment
The next record encoded opens a new one and re-sends the declarations it needs. Call this wherever a receiver may only ever see part of what was produced – before storing frames that might later be trimmed, and on reconnect.
| enc | Encoder to end the segment on |