{"id":30846362,"url":"https://github.com/jhurliman/foxglove-fdw","last_synced_at":"2026-05-09T05:34:33.443Z","repository":{"id":309618550,"uuid":"1036930569","full_name":"jhurliman/foxglove-fdw","owner":"jhurliman","description":"PostgreSQL Foreign Data Wrapper for the Foxglove API","archived":false,"fork":false,"pushed_at":"2025-08-20T19:21:16.000Z","size":44,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-07T00:09:49.456Z","etag":null,"topics":["foreign-data-wrapper","foxglove","mcap","postgresql","robotics"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jhurliman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-08-12T19:50:04.000Z","updated_at":"2025-08-20T19:22:18.000Z","dependencies_parsed_at":"2025-08-12T23:22:40.617Z","dependency_job_id":"26e15a73-81f3-484d-a091-73441b3cf72a","html_url":"https://github.com/jhurliman/foxglove-fdw","commit_stats":null,"previous_names":["jhurliman/foxglove-fdw"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jhurliman/foxglove-fdw","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhurliman%2Ffoxglove-fdw","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhurliman%2Ffoxglove-fdw/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhurliman%2Ffoxglove-fdw/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhurliman%2Ffoxglove-fdw/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jhurliman","download_url":"https://codeload.github.com/jhurliman/foxglove-fdw/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhurliman%2Ffoxglove-fdw/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32808538,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-08T08:22:46.396Z","status":"online","status_checked_at":"2026-05-09T02:00:06.633Z","response_time":123,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["foreign-data-wrapper","foxglove","mcap","postgresql","robotics"],"created_at":"2025-09-07T00:08:05.524Z","updated_at":"2026-05-09T05:34:33.414Z","avatar_url":"https://github.com/jhurliman.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# foxglove-fdw\n\nPostgreSQL Foreign Data Wrapper for the [Foxglove API](https://docs.foxglove.dev/api)\n\n# Usage\n\n### Requirements:\n\n- Docker\n- `FOXGLOVE_API_KEY` environment variable set\n\nRun `./start.sh` to build and start a local Docker container running Postgres with the Foxglove Foreign Data Wrapper installed. Connect to the database using a Postgres client (e.g., `psql` or a GUI client) with the following credentials:\n\n- Host: `localhost`\n- Port: `5432`\n- User: `postgres`\n- Password: `postgres`\n- Database: `postgres`\n\n### Querying\n\nYou can query the Foxglove API using SQL commands. Here are some examples:\n\n- List all registered devices:\n\n```sql\nSELECT * FROM devices;\n```\n\n- List all topics from a particular recording:\n\n```sql\nSELECT * FROM topics WHERE recording_id = 'rec_\u003cyour_recording_id\u003e';\n```\n\n- Total bytes recorded per device in the last 10 minutes:\n\n```sql\nSELECT device_name, SUM(size_bytes) as total_bytes\nFROM recordings\nWHERE end_time \u003e now() - interval '10 minutes'\nGROUP BY device_name\nORDER BY total_bytes DESC;\n```\n\n- Total runtime of a device in a given time period:\n\n```sql\nWITH filtered AS\n  (SELECT tstzrange(start_time, end_time, '[)') AS r\n   FROM coverage\n   WHERE tolerance = 60\n     AND device_name = '\u003cyour_device_name\u003e'\n     AND start_time \u003e '2025-01-01 06:00-08'::timestamptz\n     AND end_time \u003c now()),\nagg AS\n  (SELECT range_agg(r) AS mr FROM filtered)\nSELECT SUM(EXTRACT(EPOCH FROM (upper(x) - lower(x)))) / 60.0 AS coverage_minutes\nFROM agg, LATERAL unnest(mr) AS x;\n```\n\n- Parse all messages from a device in the last 10 minutes:\n\n```sql\nSELECT * FROM messages\nWHERE device_name = '\u003cyour_device_name\u003e'\n  AND timestamp \u003e now() - interval '10 minutes';\n```\n\n- Retrieve the most recently reported serial number for all robots that have been seen in the last week from `/robot_info.serial_number`:\n\n```sql\nWITH latest AS (\n  SELECT\n    DISTINCT ON (device_name) device_name,\n    id AS recording_id\n  FROM recordings\n  WHERE\n    import_status = 'complete'\n    AND topic = '/robot_info'\n    AND start_time \u003e now() - interval '1 week'\n  ORDER BY device_name, start_time DESC\n)\n\nSELECT\n  l.device_name,\n  m.message -\u003e\u003e 'serial_number' AS serial_number\nFROM\n  latest l\n  CROSS JOIN LATERAL (\n    SELECT message\n    FROM messages\n    WHERE\n      recording_id = l.recording_id\n      AND topic = '/robot_info'\n    ORDER BY timestamp DESC\n    LIMIT 1\n  ) m\nORDER BY l.device_name;\n```\n\n# Limitations\n\n- The messages table only supports `protobuf` and `json` encodings. Other encodings will return NULL for the message column.\n- The Foxglove API defaults to returning a maximum of 2000 rows per request (with the exception of the coverage endpoint). Automatic pagination is not currently supported, so queries that would return more than 2000 rows will be silently truncated. This limitation does not apply to the messages table which retrieves an MCAP payload and parses individual messages.\n- `FOXGLOVE_API_KEY` is currently baked into the Docker image and must be provided at build time. A future improvement would be to move this to a runtime configuration so the same container could be used with different API keys and there is no secret in the image.\n\n# License\n\nMIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjhurliman%2Ffoxglove-fdw","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjhurliman%2Ffoxglove-fdw","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjhurliman%2Ffoxglove-fdw/lists"}