OpenC3/cosmos

View on GitHub
docs/assets/js/0686a885.75974db4.js

Summary

Maintainability
A
0 mins
Test Coverage
"use strict";(self.webpackChunkdocs_openc3_com=self.webpackChunkdocs_openc3_com||[]).push([[9433],{6249:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>o,frontMatter:()=>d,metadata:()=>a,toc:()=>l});var r=n(4848),i=n(8453);const d={title:"Log Structure"},s=void 0,a={id:"development/log-structure",title:"Log Structure",description:"Updated: 8-21-2023 to the format as of OpenC3 COSMOS 5.11.0",source:"@site/docs/development/log-structure.md",sourceDirName:"development",slug:"/development/log-structure",permalink:"/docs/development/log-structure",draft:!1,unlisted:!1,editUrl:"https://github.com/OpenC3/cosmos/tree/main/docs.openc3.com/docs/development/log-structure.md",tags:[],version:"current",frontMatter:{title:"Log Structure"},sidebar:"defaultSidebar",previous:{title:"JSON API",permalink:"/docs/development/json-api"},next:{title:"Roadmap",permalink:"/docs/development/roadmap"}},c={},l=[{value:"Packet Log File Format",id:"packet-log-file-format",level:2},{value:"File Header",id:"file-header",level:3},{value:"Entry Types",id:"entry-types",level:3},{value:"Common Entry Format",id:"common-entry-format",level:4},{value:"Target Declaration Entry",id:"target-declaration-entry",level:4},{value:"Packet Declaration Entry",id:"packet-declaration-entry",level:4},{value:"Raw Packet and JSON Packet Entries",id:"raw-packet-and-json-packet-entries",level:4},{value:"Offset Marker Entry",id:"offset-marker-entry",level:4},{value:"Key Map Entry",id:"key-map-entry",level:4}];function h(e){const t={h2:"h2",h3:"h3",h4:"h4",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.p,{children:"Updated: 8-21-2023 to the format as of OpenC3 COSMOS 5.11.0"}),"\n",(0,r.jsx)(t.h2,{id:"packet-log-file-format",children:"Packet Log File Format"}),"\n",(0,r.jsx)(t.p,{children:"Packet logs in OpenC3 COSMOS 5 are used to store raw binary packets as received from various targets, as\nwell as decommutated packets stored as JSON structures."}),"\n",(0,r.jsx)(t.h3,{id:"file-header",children:"File Header"}),"\n",(0,r.jsx)(t.p,{children:'COSMOS 5 Packet log files start with the 8-character sequence "COSMOS5_". This can be used to identify the type of file independent of filename and differentiate them from newer and older versions.'}),"\n",(0,r.jsx)(t.h3,{id:"entry-types",children:"Entry Types"}),"\n",(0,r.jsx)(t.p,{children:"Packet log files have 6 different entry types with room for future expansion. All entry headers are big endian binary data."}),"\n",(0,r.jsx)(t.h4,{id:"common-entry-format",children:"Common Entry Format"}),"\n",(0,r.jsx)(t.p,{children:"This common format is used for all packet log entries:"}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"Field"}),(0,r.jsx)(t.th,{children:"Data Type"}),(0,r.jsx)(t.th,{children:"Description"})]})}),(0,r.jsxs)(t.tbody,{children:[(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Length"}),(0,r.jsx)(t.td,{children:"32-bit Unsigned Integer"}),(0,r.jsx)(t.td,{children:"Total length of the entry in bytes not including the length field. Max entry size is therefore 4GiB."})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Entry Type"}),(0,r.jsx)(t.td,{children:"4-bit Unsigned Integer"}),(0,r.jsxs)(t.td,{children:["Entry Type:",(0,r.jsx)("br",{}),"1 = Target Declaration",(0,r.jsx)("br",{}),"2 = Packet Declaraction",(0,r.jsx)("br",{}),"3 = Raw Packet",(0,r.jsx)("br",{}),"4 = JSON/CBOR Packet",(0,r.jsx)("br",{}),"5 = Offset Marker",(0,r.jsx)("br",{}),"6 = Key Map"]})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Cmd/Tlm Flag"}),(0,r.jsx)(t.td,{children:"1-bit Unsigned Integer"}),(0,r.jsxs)(t.td,{children:["1 = Command",(0,r.jsx)("br",{}),"0 = Telemetry"]})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Stored Flag"}),(0,r.jsx)(t.td,{children:"1-bit Unsigned Integer"}),(0,r.jsxs)(t.td,{children:["1 = Stored Data",(0,r.jsx)("br",{}),"0 = Realtime Data"]})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Id Flag"}),(0,r.jsx)(t.td,{children:"1-bit Unsigned Integer"}),(0,r.jsxs)(t.td,{children:["1 = ID present",(0,r.jsx)("br",{}),"0 = ID not present"]})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"CBOR Flag"}),(0,r.jsx)(t.td,{children:"1-bit Unsigned Integer"}),(0,r.jsxs)(t.td,{children:['Only Valid for "JSON/CBOR Packets"',(0,r.jsx)("br",{}),"1 = CBOR Data",(0,r.jsx)("br",{}),"0 = JSON Data"]})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Extra Flag"}),(0,r.jsx)(t.td,{children:"1-bit Unsigned Integer"}),(0,r.jsxs)(t.td,{children:["1 = Extra present",(0,r.jsx)("br",{}),"0 = Extra Not Present (Added COSMOS 5.11)"]})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Received Time Flag"}),(0,r.jsx)(t.td,{children:"1-bit Unsigned Integer"}),(0,r.jsxs)(t.td,{children:["1 = Received Time Present",(0,r.jsx)("br",{}),"0 = No Received Time (Added COSMOS 5.11.0)"]})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Reserved"}),(0,r.jsx)(t.td,{children:"6-bit Unsigned Integer"}),(0,r.jsx)(t.td,{children:"Reserved for Future expansion. Should be set to 0 if unused."})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Entry Data"}),(0,r.jsx)(t.td,{children:"Variable"}),(0,r.jsx)(t.td,{children:"Unique data based on entry type. See Entry Types Below"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Id (Optional)"}),(0,r.jsx)(t.td,{children:"32-byte Binary Hash"}),(0,r.jsx)(t.td,{children:"If the ID field is set, this is a binary 256-bit SHA-256 hash uniquely identifying a target configuration or packet configuration"})]})]})]}),"\n",(0,r.jsx)(t.h4,{id:"target-declaration-entry",children:"Target Declaration Entry"}),"\n",(0,r.jsx)(t.p,{children:"Declares the name of a target the first time it is seen when writing the log file."}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"Field"}),(0,r.jsx)(t.th,{children:"Data Type"}),(0,r.jsx)(t.th,{children:"Description"})]})}),(0,r.jsx)(t.tbody,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Target Name"}),(0,r.jsx)(t.td,{children:"Variable-Length ASCII String"}),(0,r.jsx)(t.td,{children:"Target Name"})]})})]}),"\n",(0,r.jsx)(t.h4,{id:"packet-declaration-entry",children:"Packet Declaration Entry"}),"\n",(0,r.jsx)(t.p,{children:"Declares the name of a packet the first time it is seen when writing the log file. References the associated target name by index."}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"Field"}),(0,r.jsx)(t.th,{children:"Data Type"}),(0,r.jsx)(t.th,{children:"Description"})]})}),(0,r.jsxs)(t.tbody,{children:[(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Target Index"}),(0,r.jsx)(t.td,{children:"16-bit Unsigned Integer"}),(0,r.jsx)(t.td,{children:"Index into a dynamically built table of target names, generated from the order of the target declarations in the file. The first target declaration gets index 0, the second target declaration gets index 1, etc."})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Packet Name"}),(0,r.jsx)(t.td,{children:"Variable-Length ASCII String"}),(0,r.jsx)(t.td,{children:"Packet Name"})]})]})]}),"\n",(0,r.jsx)(t.h4,{id:"raw-packet-and-json-packet-entries",children:"Raw Packet and JSON Packet Entries"}),"\n",(0,r.jsx)(t.p,{children:'Holds the main data for a packet. Raw packets are the data before the COSMOS decommutation phase. "JSON" packets are the data after decommutation. Note that "JSON" packets are now generally stored as CBOR rather than JSON to reduce storage size.'}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"Field"}),(0,r.jsx)(t.th,{children:"Data Type"}),(0,r.jsx)(t.th,{children:"Description"})]})}),(0,r.jsxs)(t.tbody,{children:[(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Packet Index"}),(0,r.jsx)(t.td,{children:"16-bit Unsigned Integer"}),(0,r.jsx)(t.td,{children:"Index into a dynamically built table of cmd_or_tlm/target name/packet name tuples, generated from the order of the packet declarations in the file. The first packet declaration gets index 0, the second packet declaration gets index 1, etc. This limits the max number of unique packet types in a single file to 65536."})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Packet Timestamp"}),(0,r.jsx)(t.td,{children:"64-bit Unsigned Integer"}),(0,r.jsx)(t.td,{children:"Packet timestamp in nanoseconds from the unix epoch (Jan 1st, 1970, midnight). This field contains the \u201cpacket time\u201d for both Raw and JSON packet entries (which are used to store decommutated date). For JSON packet entries, the packet received time can also be extracted from the JSON data if needed."})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Received Timestamp (Optional)"}),(0,r.jsx)(t.td,{children:"64-bit Unsigned Integer"}),(0,r.jsx)(t.td,{children:"Only present if Received Time Flag is Set (Only currently in Raw log files). Received timestamp in nanoseconds from the unix epoch (Jan 1st, 1970, midnight). This field contains the received time\u201d for both Raw packet entries (which are used to store decommutated date). For JSON packet entries, the packet received time can be extracted from the JSON data if needed."})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Extra Length (Optional)"}),(0,r.jsx)(t.td,{children:"32-bit Unsigned Integer"}),(0,r.jsx)(t.td,{children:"Only Present if Extra Flag is Set. Length of extra data in bytes not including itself."})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Extra Data (Optional)"}),(0,r.jsx)(t.td,{children:"Variable-Length Block Data"}),(0,r.jsx)(t.td,{children:"Only Present if Extra Flag is Set. CBOR or JSON encoded object of extra data."})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Packet Data"}),(0,r.jsx)(t.td,{children:"Variable-Length Block Data"}),(0,r.jsx)(t.td,{children:"The Raw binary packet data for Raw Packet entries, and ASCII JSON data (or CBOR if flag set) for JSON packet entries. Note the Common Entry Format Id field is not supported with either type of packet entry."})]})]})]}),"\n",(0,r.jsx)(t.h4,{id:"offset-marker-entry",children:"Offset Marker Entry"}),"\n",(0,r.jsx)(t.p,{children:"This contains the Redis stream offset for the last packet stored in this log file. This entry allows for a seamless transition from log files to Redis streams holding the most recent data received by COSMOS."}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"Field"}),(0,r.jsx)(t.th,{children:"Data Type"}),(0,r.jsx)(t.th,{children:"Description"})]})}),(0,r.jsx)(t.tbody,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Offset Marker"}),(0,r.jsx)(t.td,{children:"Variable-Length ASCII String"}),(0,r.jsx)(t.td,{children:"Redis Offset Marker"})]})})]}),"\n",(0,r.jsx)(t.h4,{id:"key-map-entry",children:"Key Map Entry"}),"\n",(0,r.jsx)(t.p,{children:"The key map entry is used to further reduce log file sizes by reducing the size of the names of the decommutated values. Each value is given a numeric name counting up from 0 which drastically reduces decommutated data size. Note: This could be further enhanced in the future by changing to a denser encoding similar to base64. The key map is generated on the first reception of a packet. If future packets have different keys, then the names are used as-is and no reduction is gained. Typically packet keys don't change within a file."}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"Field"}),(0,r.jsx)(t.th,{children:"Data Type"}),(0,r.jsx)(t.th,{children:"Description"})]})}),(0,r.jsxs)(t.tbody,{children:[(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Packet Index"}),(0,r.jsx)(t.td,{children:"16-bit Unsigned Integer"}),(0,r.jsx)(t.td,{children:"Index into a dynamically built table of packet names, generated from the order of the packet declarations in the file. The first packet declaration gets index 0, the second packet declaration gets index 1, etc."})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Key Map"}),(0,r.jsx)(t.td,{children:"Variable-Length ASCII String"}),(0,r.jsx)(t.td,{children:"Key Map Data with Mapping from numeric key to actual packet item name"})]})]})]})]})}function o(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>a});var r=n(6540);const i={},d=r.createContext(i);function s(e){const t=r.useContext(d);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),r.createElement(d.Provider,{value:t},e.children)}}}]);