{"id":24772588,"url":"https://github.com/codaea/browser-exporter","last_synced_at":"2026-04-28T20:37:24.875Z","repository":{"id":274385719,"uuid":"907462929","full_name":"Codaea/browser-exporter","owner":"Codaea","description":"A prometheus exporter for your chrome browser","archived":false,"fork":false,"pushed_at":"2025-01-27T01:05:31.000Z","size":77,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-23T20:45:11.752Z","etag":null,"topics":["extension-chrome","prometheus-exporter","pushgateway"],"latest_commit_sha":null,"homepage":"https://codaea.com/things/broswermetrics","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Codaea.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2024-12-23T16:29:36.000Z","updated_at":"2025-02-23T02:21:42.000Z","dependencies_parsed_at":"2025-01-27T01:25:31.247Z","dependency_job_id":"06d97dff-da05-46c4-b8a4-055af1c1742f","html_url":"https://github.com/Codaea/browser-exporter","commit_stats":null,"previous_names":["codaea/browser-exporter"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Codaea%2Fbrowser-exporter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Codaea%2Fbrowser-exporter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Codaea%2Fbrowser-exporter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Codaea%2Fbrowser-exporter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Codaea","download_url":"https://codeload.github.com/Codaea/browser-exporter/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245168809,"owners_count":20571799,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["extension-chrome","prometheus-exporter","pushgateway"],"created_at":"2025-01-29T04:23:28.981Z","updated_at":"2026-04-28T20:37:24.818Z","avatar_url":"https://github.com/Codaea.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# browser-exporter\n\nExport statistics from your browser to prometheus via pushgateway.\n\n## Avalible Metrics\n\n- browser_bookmarks\n- browser_bookmarks_created\n- browser_memory_available_bytes\n- browser_existing_bytes\n- browser_tab_zoom_factor\n- browser_tabs_active\n- browser_tabs_blank\n- browser_tabs_changed\n- browser_tabs_closed\n- browser_tabs_currentactive\n- browser_tabs_discarded\n- browser_tabs_muted\n- browser_tabs_open\n- browser_tabs_opened\n- browser_webrequests_completed_total\n- browser_webrequests_error_total\n- browser_windows_open\n- browser_windows_closed\n- browser_windows_opened\n\nall metrics are labeled with a UUID generated by the extension.\n\n## Architecture\n\n![architecture.png](./docs/content/architecture.png)\n\nbrowser exporter pushes to prometheus pushgateway, that is then scraped by\nprometheus.\n\nnot shown, but a reverse proxy is **REQUIRED** between pushgatway and browser\nexporter, as chrome's `manifest.json` only allows https traffic.\n\n## Self-Hosting\n\nThe extension really just needs a pushgateway to send information to, but here is the docker compose that I use in production for the public instance.\n\n```yml \nservices:\n  prometheus:\n    image: prom/prometheus\n    command:\n      - '--config.file=/etc/prometheus/prometheus.yml'\n      - '--storage.tsdb.path=/prometheus'\n      - '--storage.tsdb.retention.time=90d'\n    volumes:\n      - \"${PWD}/prometheus.yml:/etc/prometheus/prometheus.yml\"\n      - \"${PWD}/data:/prometheus\"\n    ports:\n      - \"9090:9090\"\n  pushgateway:\n    image: prom/pushgateway\n    container_name: pushgateway\n    restart: unless-stopped\n    ports:\n      - \"9091:9091\"\n  proxy_server:\n    image: nginx\n    ports:\n      - \"9092:80\"\n    volumes:\n      - \"${PWD}/nginx.conf:/etc/nginx/conf.d/default.conf\"\n```\n\nA reverse proxy is required, due to `known_hosts` being set to a https scheme.\n**Preflight CORS** is  handled by nginx, with the following config\n(along with some basic hardening)\n\n```nginx\nserver {\n    listen 80;\n    server_name proxy_server;\n    # Allow POST requests to /metrics/job/* and handle CORS preflight\n    location ~ ^/metrics/job/.*$ {\n        # Handle CORS Preflight (OPTIONS)\n        if ($request_method = 'OPTIONS') {\n            add_header 'Access-Control-Allow-Origin' '*' always;\n            add_header 'Access-Control-Allow-Methods' 'POST, OPTIONS' always;\n            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;\n            add_header 'Access-Control-Max-Age' 1728000 always;\n            add_header 'Content-Type' 'text/plain; charset=utf-8' always;\n            add_header 'Content-Length' 0 always;\n            return 204;\n        }\n\n        # Handle POST requests\n        if ($request_method != 'POST') {\n            return 405; # Method Not Allowed for anything other than POST\n        }\n\n        add_header 'Access-Control-Allow-Origin' '*' always;\n        add_header 'Access-Control-Allow-Methods' 'POST, OPTIONS' always;\n        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;\n        add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;\n\n        # Pass POST requests to the pushgateway backend\n        proxy_pass http://pushgateway:9091;\n    }\n\n    location / {\n        return 200 \"nice try\";\n    }\n\n   access_log /var/log/nginx/access.log;\n   error_log /var/log/nginx/error.log;\n}\n```\nprometheus.yml is just \n\n```yml\nglobal:\n  scrape_interval: 15s\n\nscrape_configs:\n  - job_name: \"pushgateway\"\n    honor_labels: true\n    static_configs:\n    - targets: [ 'pushgateway:9091' ]\n```\n\n\n## Development\n\nfor building chrome extensions, vite and [crxjs](https://crxjs.dev/vite-plugin/) are used.\n\n```bash\n# install dependencies\nnpm i\n\n# start development server\nnpm run dev \n\n# build to /dist\nnpm run build\n```\n\nTo add extension to browser, go to `chrome://extensions` and enable developer,\nthen `Load Unpacked extension`, navigate to `dist`, then load.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodaea%2Fbrowser-exporter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodaea%2Fbrowser-exporter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodaea%2Fbrowser-exporter/lists"}