{"id":28100061,"url":"https://github.com/ttencate/attolytics","last_synced_at":"2026-04-29T01:32:02.652Z","repository":{"id":66858342,"uuid":"179120023","full_name":"ttencate/attolytics","owner":"ttencate","description":"A small web service that receives analytics events and inserts them into a PostgreSQL database","archived":false,"fork":false,"pushed_at":"2024-02-09T05:18:34.000Z","size":67,"stargazers_count":2,"open_issues_count":1,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-13T18:06:27.047Z","etag":null,"topics":["postgresql","rest","rust"],"latest_commit_sha":null,"homepage":null,"language":"Rust","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/ttencate.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":"2019-04-02T16:45:04.000Z","updated_at":"2024-08-18T17:15:43.000Z","dependencies_parsed_at":"2023-05-11T22:30:27.749Z","dependency_job_id":null,"html_url":"https://github.com/ttencate/attolytics","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ttencate/attolytics","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttencate%2Fattolytics","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttencate%2Fattolytics/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttencate%2Fattolytics/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttencate%2Fattolytics/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ttencate","download_url":"https://codeload.github.com/ttencate/attolytics/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttencate%2Fattolytics/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32407164,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-28T19:38:08.556Z","status":"ssl_error","status_checked_at":"2026-04-28T19:37:55.688Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["postgresql","rest","rust"],"created_at":"2025-05-13T18:01:51.783Z","updated_at":"2026-04-29T01:32:02.646Z","avatar_url":"https://github.com/ttencate.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"Attolytics\n==========\n\nAttolytics (a portmanteau of the SI prefix \"atto\" meaning 10\u003csup\u003e-18\u003c/sup\u003e and\n\"analytics\") is a small web service that receives analytics events and inserts\nthem into a PostgreSQL database. These events can subsequently be processed and\ndisplayed using frameworks like [Cube.js](https://cube.dev/), but that is\noutside the scope of this application.\n\nAttolytics is written in [Rust](https://rust-lang.org/) using the\n[Rocket](https://rocket.rs/) framework.\n\nCompiling\n---------\n\n* Install Rust nightly, e.g.\n  [using rustup](https://www.rust-lang.org/tools/install).\n\n* Clone this repository:\n\n        $ git clone https://github.com/ttencate/attolytics\n\n* Compile the binary:\n\n        $ cargo build --release\n\nRunning\n-------\n\n* Set up PostgreSQL using some appropriate guide for your system.\n\n* Create a database, e.g. owned by your current user and named `attolytics`:\n\n        $ createdb -o $(whoami) attolytics\n\n* Create a schema file, typically named `schema.conf.yaml`. This file tells\n  Attolytics which tables exist, and which apps write to which tables. See\n  [`schema-example.conf.yaml`](schema-example.conf.yaml) for a documented\n  example of the format.\n\n* Run the executable, passing it the location of your schema file and the URL\n  of your database:\n\n        $ ./target/release/attolytics --schema ./schema.conf.yaml --db_url postgres://$(whoami)@localhost/attolytics\n\n  For full documentation of supported options, run:\n\n        $ ./target/release/attolytics --help\n\nDeploying\n---------\n\nSystemd launch notifications are supported. So to run Attolytics on a Linux\nmachine with systemd behind an nginx proxy, a unit file like the following can\nbe used:\n\n**`/etc/systemd/system/attolytics.service`**\n\n    [Unit]\n    Description=Attolytics analytics events ingestion service\n    Requires=network.target\n    After=network.target\n\n    [Service]\n    Type=notify\n    NotifyAccess=main\n    WorkingDirectory=/var/www/attolytics.frozenfractal.com\n    ExecStart=/path/to/attolytics --schema /path/to/schema.conf.yaml --db_url postgres://attolytics@%%2Frun%%2Fpostgresql --port 8005 --verbose\n    User=attolytics\n    Group=attolytics\n    Restart=on-failure\n\n    [Install]\n    WantedBy=nginx.service\n\nNote that a warning will be emitted in the logs:\n\n    Warning: environment is 'production', but no `secret_key` is configured\n\nThis is harmless, because this `secret_key` is not related to the per-app\n`secret_key` specified it the schema. This one here is only [used by the Rocket\nframework](https://rocket.rs/v0.4/guide/requests/#secret-key) to encrypt\ncookies, but Attolytics doesn't use cookies.\n\nHere is the corresponding nginx configuration:\n\n**`/etc/nginx/sites-enabled/attolytics.conf`**\n\n    upstream attolytics {\n      server 127.0.0.1:8005 fail_timeout=0;\n    }\n\n    server {\n      server_name attolytics.example.com;\n      listen 443 ssl;\n\n      location / {\n        proxy_pass http://attolytics;\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $remote_addr;\n        proxy_set_header X-Forwarded-Proto $scheme;\n      }\n\n      ssl_certificate /path/to/fullchain.pem;\n      ssl_certificate_key /path/to/privkey.pem;\n    }\n\nREST API\n--------\n\nEvents can be inserted into the database by making an HTTP POST request. One\nendpoint exists for every event type of every app:\n\n    POST /apps/\u003capp_id\u003e/events\n    Content-Type: application/json\n\n    {\n      \"secret_key\": \"\u003capp_secret_key\u003e\",\n      \"events\": [\n        ...\n      ]\n    }\n\nThe `events` array contains the events to be uploaded. Each event is an object,\nwhich must contain these fields:\n\n* `_t`: name of the table to insert into\n\nThe remainder of the fields must have keys matching column names in PostgreSQL.\nThe corresponding values must be of the correct type for those columns.\n\nContinuing with the above example of the `game_events` table:\n\n      \"events\": [\n        {\"_t\": \"events\", \"timestamp\": 1554130180, \"event_type\": \"game_start\"},\n        {\"_t\": \"events\", \"timestamp\": 1554130213, \"event_type\": \"game_end\", \"score\": 42}\n      ]\n\nSchema changes\n--------------\n\nIf you want to add, remove or alter columns in a table, this requires some\nmanual work:\n\n* Stop the server.\n* Update the configuration file.\n* Update the database using `ALTER TABLE` statements.\n* Start the server.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fttencate%2Fattolytics","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fttencate%2Fattolytics","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fttencate%2Fattolytics/lists"}