Giter Club home page Giter Club logo

timetrackrs's Introduction

How did you spend your day?

teaser

plot screenshot

Track which projects you are working on and how much

timeline example

Add your own custom classification rules...

custom rules

...to get more detail

detailed plot screenshot

timetrackrs - an automatic rule-based time tracker

timetrackrs tracks what you spend your time on and stores it in a database. Inspired by arbtt, which I used previously.

Provides a Web UI to analyze it and create custom rules to improve the classification.

The user activity is tracked as "events", where each events has a timestamp, a duration, and a set of tags with values. You can think of tags as basically an extension of categories, allowing multiple category trees.

For example, an event can may have the following tags:

  • category:Productivity/Software Development/IDE
  • project:2021/timetrackrs
  • device:Home-PC

Which means in the UI you can figure out the time spent on software development, or on a specific project (not necessarily software development), or on a specific device.

Setup / Building

Note that this tool is not yet finished. There are no prebuilt binaries available yet.

git clone https://github.com/phiresky/timetrackrs.git
cd timetrackrs
# build frontend first
cd frontend
yarn install
yarn build
cd ..
# build and install `timetrackrs` binary to ~/.cargo/bin
./update-schemas.sh
cargo install --path .

You should start timetrackrs on user login. It will start the UI at http://localhost:52714/dashboard and start the default window tracking data source.

If you use systemd, you can use the included [timetrackrs.service] service file to auto-start timetrackrs.

Note for building in Windows: If you're experiencing an error related to openssl-sys either install the OpenSSL Library properly via vcpkg or add the --features openssl-vendored argument to the installation command, such as:

#build and install `timetrackrs` binary to ~/.cargo/bin
cargo install --features openssl-vendored --path .

Development

First, generate the dev-db needed for sqlx compilation:

./update-schemas.sh

To start a timetrackrs server (backend + frontend) without any capturing, you can run

RUST_LOG=debug,sqlx=warn,hyper=warn cargo run --bin timetrackrs -- --config data/debug_config.json

To continuously rebuild the frontend, do

cd frontend
yarn dev

Data Sources

Working Data Sources

  • Linux X11 tracking. Tracks the following properties:

    • Which program is open (binary name)
    • The window title
    • Which file does the program have open (via cmd args)
    • Connected WiFi (to be able to figure out rough location)
    • Some stats about the system

    Adds the following intrinsic tags:

    • software-window-title:...
    • software-executable-path:...
    • software-window-class:<X11 window class>
    • software-opened-file:<file path>
    • device-hostname:...

    and more.

  • App Usage import

    Allows tracking which apps / app categories are used on your Android devices.

    • device-hostname:...
    • device-type:<tablet or phone>
    • android-packageid:<play store package id>
    • software-name:<App Name>
    • device-os-type:Android
  • Browser Usage

    Tracks which websites / domains are used.

    Adds the following tags:

    • browse-url:https://...
    • browse-full-domain:news.ycombinator.com
    • browse-domain:ycombinator.com
  • VS Code tracking

    Tracks which software development projects you spend your time on, as well as which files.

    To enable, open your user settings and set window.title to ${dirty}${activeEditorShort}${separator}${rootName}${separator}${appName}} 🛤sd🠚proj=${rootPath}🙰file=${activeEditorMedium}🠘

    Adds the following tags:

    • software-development-project:<project-path>
  • Sleep As Android import

    Imports data of when and how you slept from the Sleep app.

    Creates events with the following tags:

    • physical-activity:sleeping
  • Timetrackrs import

    Imports data from a different timetrackrs database (e.g. from another device).

  • ZSH shell usage

    Adds the following tags:

    • title-match-shell-cwd:<current working directory>
    • title-match-shell-usr:<current username>
    • title-match-shell-cmd:<currently running program>

    To enable, install zsh-histdb, then add the following to your .zshrc:

    # set window title for timetrackrs
    # adopted from https://github.com/ohmyzsh/ohmyzsh/blob/master/lib/termsupport.zsh
    autoload -Uz add-zsh-hook
    
    function title_precmd {
        title_preexec '' ''
    }
    function title_preexec {
        # http://zsh.sourceforge.net/Doc/Release/Expansion.html
        # http://zsh.sourceforge.net/Doc/Release/Prompt-Expansion.html#Prompt-Expansion
        local cwd="$(print -P '%~')"
        local user="$(print -P '%n@%m')"
        local LINE="$2"
        local cmd="$(print -P '%100>...>$LINE%<<')"
    
        title '' '{"t":"shell","cwd":${(qqq)cwd},"histdb":$HISTDB_SESSION,"usr":${(qqq)user},"cmd":${(qqq)cmd}}'
    }
    add-zsh-hook precmd title_precmd
    add-zsh-hook preexec title_preexec
    

Todo Data Sources

  • Fix Windows data source
  • More detailed browser usage (which containers are used, how did you get to website X?). Needs own webextension
  • mpv usage via (which TV shows and movies watched), via own mpv tracking lua script .config/mpv/scripts/logall.lua
  • Google Fitness import via API
  • Manual entry UI to add start/stop times and categories by hand.

External Info Fetchers

Timetrackrs supports fetching additional information from external sources.

Currently, the following are implemented:

  • Youtube Meta Fetcher

    Fetches some metadata when watching videos like the youtube category (Music / Educational / Entertainment / etc) and the channel. Adds the following tags:

    • youtube-channel:<uploader channel id>
    • youtube-channel-name:<uploader username>
    • youtube-tag:<tag-value> for each tag
    • youtube-category:<category> for each video category
  • Wikidata fetcher

    For each domain visited, tries to get some info about that domain from Wikidata. Adds the following tags.

    Adds the following tags when visiting e.g. reddit.com:

    • wikidata-label:Reddit
    • wikidata-id:Q1136
    • wikidata-category:social networking service
    • wikidata-category:social-news website
    • wikidata-category:mobile app

General Todo

Ideas for getting program metadata

Metadata we could potentially get:

  • Get open files from /proc/pid/fd
  • This program name can be mapped to a software package using the system package manager, example: pacman -Qo /usr/bin/vlc. Then that package name can be used to get metadata, for example the software homepage, tags etc.

Technical details

Philosophy

Store as much information in an as raw as possible format in the capture step. Interpret / make it usable later in the analyse step. This prevents accidentally missing interesting information when saving and can allow reinterpretions in unexpected ways later. Redundancies in the data which cause large storage requirements will be solved with compression later.

This is similar to arbtt, and specifically different to many other time tracking alternatives such as ActivityWatch, which stores processed data only.

Rule application

Each event has a set of "intrinsic tags" given by the data source. For example, an intrinsic tag of the window tracking data source would be window-title:Hey there! - Youtube - https://youtube.com/watch?v=xyz

Then there is a set of rules that add more tags based on existing tags. These are either simple derivations like "if software-executable-basename:vlc then add category:Entertainment" or based on external fetchers that retrieve data from external sources.

The rules are applied iteratively until settled. Here is an example rule derivation chain (you can view this for any tag in the UI):

Yesterday at 4:51 pm, you spent 30s in category: Entertainment/Video.

Derivation:

  1. The data source x11_v2 has the intrinsic tag software-window-title:Bloons TD 6 - YouTube - https://www.youtube.com/watch?v=bs-AUJF9nhs — Firefox
  2. The tag software-window-title matched the regex ^.*(?P<url>https?://[-a-zA-Z0-9@:%._\+~#=]{1,256}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)).*$, so the rule browse-url:$url in Default Rules added the tag browse-url:https://www.youtube.com/watch?v=bs-AUJF9nhs
  3. The InternalFetcher url-domain-matcher matched on the tag browse-url and added the tag browse-main-domain:youtube.com
  4. The ExternalFetcher youtube-meta-json matched on the tag browse-main-domain:youtube.com and queried YouTube to get the tags and categories, adding the tag youtube-category:Gaming.
  5. The tag youtube-category matched the regex ^(Gaming|Entertainment)$ so a rule in Default Rules added the tag category:Entertainment/Video.

Compression notes

Finish and make use of https://github.com/phiresky/sqlite-zstd. Then redundancy in the stored raw events should become basically irrelevant.

Compression benchmark:

for id in $(sqlite3 activity.sqlite3 "select id from events where data_type='x11'"); do sqlite3 activity.sqlite3 "select data from events where id='$id'" > "x11/$id.json"; done

Zstd test: 7400 x11 events rows:

  • 202M uncompressed (27kB avg)
  • 21M compressed without dictionary (2.8kbyte avg)
  • 20M compressed with xz -9
  • 5.0M compressed with generated dictionary (675byte avg), 110KB dictionary-file (which is default --maxdict)
  • 12M compressed with random sample json file as dictionary (1.6kbyte avg)
  • 11M compressed with dict generated 100 random json files (20kb dict file)
  • 2.7M compressed with large dict, 1MB dict file size (--maxdict=1000000)
  • 1.9MB as single file: zstd -19 all
  • 1.6MB as single file: zstd --ultra -22 --long=31 all
  • 1.3MB as single file (ordered by date) -19
  • 1.3MB as single file (ordered by date) --ultra -22 --long=31

Conclusion: zstd is awesome

Comparison to other tools

ActivityWatch

ActivityWatch is fairly similar, but it has a very different philosophy regarding the collected data (see above). It also has no option to fetch metadata from external sources, and the plugins are limited to the same computer (no import from a phone or some API like fitness or sleep tracking or similar).

I actually opened an issue in the ActivityWatch repo with some of the things I learned while writing timetrackrs, since so far it's not clear if I'll get timetrackrs to a production ready state.

Arbtt

  • Only tracks open programs
  • The performance does not scale well with db size, the analyze step always has to go through the whole database. Timetrackrs caches the extracted data in a separate database.
  • I've had a lot of database corruption issues in the past with it. Timetrackrs uses sqlite which is pretty safe.
  • No Web-UI, creating rules is hard
  • No external data fetchers, no importing from other apps

timetrackrs's People

Contributors

flappybug avatar phiresky avatar selyatin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

timetrackrs's Issues

Windows build failed - openssl & vcpkg

So I tried to install, but I am getting this error, the same as in README.

error: failed to run custom build command for `openssl-sys v0.9.80`

However solutions from README doesn't work for me.

Not sure what info to provide.

build failed on Windows

I tried to install it on Windows, with a new node and yarn installation, and it fails:

error C:\tmp\timetrackrs\frontend\node_modules\husky: Command failed.
Exit code: 1
Command: node husky install
Arguments:
Directory: C:\tmp\timetrackrs\frontend\node_modules\husky
Output:
husky > Setting up git hooks
Cannot read properties of null (reading 'toString')



C:\tmp\timetrackrs\frontend>node --version
v16.13.0

[ERROR] esbuild error when trying to build on FreeBSD

OS: FreeBSD 13.2-STABLE

Hi, I get this error when trying to build on FreeBSD:

/usr/home/yaslam/Git/timetrackrs/frontend/.pnp.cjs:17895
  return Object.defineProperties(new Error(message), {
                                 ^

Error: Your application tried to access esbuild, but it isn't declared in your dependencies; this makes the require call ambiguous and unsound.

Required package: esbuild (via "esbuild/package.json")
Required by: /usr/home/yaslam/Git/timetrackrs/frontend/.yarn/__virtual__/vite-virtual-ec6cd84b7e/4/.yarn/berry/cache/vite-npm-4.0.4-33a47fc7a2-9.zip/node_modules/vite/dist/node/cli.js

    at makeError (/usr/home/yaslam/Git/timetrackrs/frontend/.pnp.cjs:17895:34)
    at resolveToUnqualified (/usr/home/yaslam/Git/timetrackrs/frontend/.pnp.cjs:19313:21)
    at Object.resolveToUnqualified (/usr/home/yaslam/Git/timetrackrs/frontend/.pnp.cjs:19503:26)
    at resolve$1 (file:///usr/home/yaslam/Git/timetrackrs/frontend/.pnp.loader.mjs:2009:31)
    at nextResolve (node:internal/modules/esm/loader:163:28)
    at ESMLoader.resolve (node:internal/modules/esm/loader:835:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:424:18)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:77:40)
    at link (node:internal/modules/esm/module_job:76:36)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

Node.js v18.17.1

Broken on Firefox 96 beta

probably a firefox bug. Temporal.Now.zonedDateTimeISO() throws Uncaught TypeError: can't access property "split", time is undefined

normal (firefox 90, chrome,...):

 new Intl.DateTimeFormat('en-us', {
        timeZone: "UTC",
        hour12: false,
        era: 'short',
        year: 'numeric',
        month: 'numeric',
        day: 'numeric',
        hour: 'numeric',
        minute: 'numeric',
        second: 'numeric'
      }).format(new Date())`

normal output:

'12 10, 2021 AD, 19:37:23'

firefox 96 output:

"12/10/2021 A, 19:42:34"

Windows + MacOS service / autorun

Create a simple way to install timetrackrs as a service such that

  • it automatically starts on login
  • restarts when it crashes due to an error

Both are already implemented on Linux with the included systemd user service.

On Windows, the state of the art would probably be to create a MSIX package that installs timetrackrs as a system service (e.g. reference: https://docs.microsoft.com/en-us/windows/msix/packaging-tool/convert-an-installer-with-services) There's some rust crate that helps with this I think.

On MacOS, I have no idea how to do this properly.

'tokio-runtime-worker' panicked at 'not zero terminated'

Hi, I use Linux 5.4.0-94-generic #106-Ubuntu x86_64 GNU/Linux

after building I run RUST_BACKTRACE=1 ~/.cargo/bin/timetrackrs and have this output:

2022-01-20T18:34:44.713231Z  INFO timetrackrs::db: Running 6 migrations 
Configuration: TimetrackrsConfig {
    capturers: [
        CaptureConfig {
            interval: 30s,
            args: NativeDefault(
                NativeDefaultArgs,
            ),
        },
    ],
    server: Some(
        ServerConfig {
            listen: [
                "127.0.0.1:52714",
            ],
        },
    ),
}
starting server at http://127.0.0.1:52714
new id generated: c7kqmh04ooc839fc5gc0
2022-01-20T18:34:44.808347Z  INFO timetrackrs::capture: sleeping 30s
thread 'tokio-runtime-worker' panicked at 'not zero terminated', src/capture/linux/types.rs:121:9
stack backtrace:
reporting root done
   0: std::panicking::begin_panic
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/std/src/panicking.rs:604:12
   1: timetrackrs::capture::linux::types::split_zero
             at ./src/capture/linux/types.rs:121:9
   2: <timetrackrs::capture::linux::x11::X11Capturer<C> as timetrackrs::capture::Capturer>::capture
             at ./src/capture/linux/x11.rs:123:29
   3: timetrackrs::capture::capture_loop::{{closure}}
             at ./src/capture/mod.rs:67:20
   4: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/core/src/future/mod.rs:84:19
   5: tokio::runtime::task::core::CoreStage<T>::poll::{{closure}}
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/task/core.rs:161:17
   6: tokio::loom::std::unsafe_cell::UnsafeCell<T>::with_mut
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/loom/std/unsafe_cell.rs:14:9
   7: tokio::runtime::task::core::CoreStage<T>::poll
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/task/core.rs:151:13
   8: tokio::runtime::task::harness::poll_future::{{closure}}
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/task/harness.rs:461:19
   9: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/core/src/panic/unwind_safe.rs:271:9
  10: std::panicking::try::do_call
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/std/src/panicking.rs:485:40
  11: std::panicking::try
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/std/src/panicking.rs:449:19
  12: std::panic::catch_unwind
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/std/src/panic.rs:136:14
  13: tokio::runtime::task::harness::poll_future
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/task/harness.rs:449:18
  14: tokio::runtime::task::harness::Harness<T,S>::poll_inner
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/task/harness.rs:98:27
  15: tokio::runtime::task::harness::Harness<T,S>::poll
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/task/harness.rs:53:15
  16: tokio::runtime::task::raw::RawTask::poll
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/task/raw.rs:70:18
  17: tokio::runtime::task::LocalNotified<S>::run
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/task/mod.rs:343:9
  18: tokio::runtime::thread_pool::worker::Context::run_task::{{closure}}
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/thread_pool/worker.rs:420:13
  19: tokio::coop::with_budget::{{closure}}
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/coop.rs:102:9
  20: std::thread::local::LocalKey<T>::try_with
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/std/src/thread/local.rs:413:16
  21: std::thread::local::LocalKey<T>::with
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/std/src/thread/local.rs:389:9
  22: tokio::coop::with_budget
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/coop.rs:95:5
  23: tokio::coop::budget
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/coop.rs:72:5
  24: tokio::runtime::thread_pool::worker::Context::run_task
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/thread_pool/worker.rs:419:9
  25: tokio::runtime::thread_pool::worker::Context::run
  26: tokio::runtime::thread_pool::worker::run::{{closure}}
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/thread_pool/worker.rs:371:17
  27: tokio::macros::scoped_tls::ScopedKey<T>::set
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/macros/scoped_tls.rs:61:9
  28: tokio::runtime::thread_pool::worker::run
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/thread_pool/worker.rs:368:5
  29: tokio::runtime::thread_pool::worker::Launch::launch::{{closure}}
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/thread_pool/worker.rs:347:45
  30: <tokio::runtime::blocking::task::BlockingTask<T> as core::future::future::Future>::poll
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/blocking/task.rs:42:21
  31: tokio::runtime::task::core::CoreStage<T>::poll::{{closure}}
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/task/core.rs:161:17
  32: tokio::loom::std::unsafe_cell::UnsafeCell<T>::with_mut
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/loom/std/unsafe_cell.rs:14:9
  33: tokio::runtime::task::core::CoreStage<T>::poll
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/task/core.rs:151:13
  34: tokio::runtime::task::harness::poll_future::{{closure}}
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/task/harness.rs:461:19
  35: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/core/src/panic/unwind_safe.rs:271:9
  36: std::panicking::try::do_call
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/std/src/panicking.rs:485:40
  37: std::panicking::try
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/std/src/panicking.rs:449:19
  38: std::panic::catch_unwind
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/std/src/panic.rs:136:14
  39: tokio::runtime::task::harness::poll_future
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/task/harness.rs:449:18
  40: tokio::runtime::task::harness::Harness<T,S>::poll_inner
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/task/harness.rs:98:27
  41: tokio::runtime::task::harness::Harness<T,S>::poll
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/task/harness.rs:53:15
  42: tokio::runtime::task::raw::RawTask::poll
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/task/raw.rs:70:18
  43: tokio::runtime::task::UnownedTask<S>::run
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/task/mod.rs:379:9
  44: tokio::runtime::blocking::pool::Inner::run
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/blocking/pool.rs:264:17
  45: tokio::runtime::blocking::pool::Spawner::spawn_thread::{{closure}}
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/blocking/pool.rs:244:17
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Error: panic

Stack backtrace:
   0: anyhow::error::<impl core::convert::From<E> for anyhow::Error>::from
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/anyhow-1.0.52/src/error.rs:530:25
   1: <core::result::Result<T,F> as core::ops::try_trait::FromResidual<core::result::Result<core::convert::Infallible,E>>>::from_residual
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/core/src/result.rs:2052:27
   2: timetrackrs::main::{{closure}}
             at ./src/bin/timetrackrs.rs:86:9
   3: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/core/src/future/mod.rs:84:19
   4: tokio::park::thread::CachedParkThread::block_on::{{closure}}
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/park/thread.rs:263:54
   5: tokio::coop::with_budget::{{closure}}
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/coop.rs:102:9
   6: std::thread::local::LocalKey<T>::try_with
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/std/src/thread/local.rs:413:16
   7: std::thread::local::LocalKey<T>::with
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/std/src/thread/local.rs:389:9
   8: tokio::coop::with_budget
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/coop.rs:95:5
   9: tokio::coop::budget
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/coop.rs:72:5
  10: tokio::park::thread::CachedParkThread::block_on
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/park/thread.rs:263:31
  11: tokio::runtime::enter::Enter::block_on
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/enter.rs:151:13
  12: tokio::runtime::thread_pool::ThreadPool::block_on
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/thread_pool/mod.rs:77:9
  13: tokio::runtime::Runtime::block_on
             at /home/i/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/mod.rs:463:43
  14: timetrackrs::main
             at ./src/bin/timetrackrs.rs:90:5
  15: core::ops::function::FnOnce::call_once
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/core/src/ops/function.rs:227:5
  16: std::sys_common::backtrace::__rust_begin_short_backtrace
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/std/src/sys_common/backtrace.rs:123:18
  17: std::rt::lang_start::{{closure}}
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/std/src/rt.rs:145:18
  18: core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/core/src/ops/function.rs:259:13
  19: std::panicking::try::do_call
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/std/src/panicking.rs:485:40
  20: std::panicking::try
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/std/src/panicking.rs:449:19
  21: std::panic::catch_unwind
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/std/src/panic.rs:136:14
  22: std::rt::lang_start_internal::{{closure}}
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/std/src/rt.rs:128:48
  23: std::panicking::try::do_call
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/std/src/panicking.rs:485:40
  24: std::panicking::try
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/std/src/panicking.rs:449:19
  25: std::panic::catch_unwind
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/std/src/panic.rs:136:14
  26: std::rt::lang_start_internal
             at /rustc/5e57faa78aa7661c6000204591558f6665f11abc/library/std/src/rt.rs:128:20
  27: main
  28: __libc_start_main
  29: _start

capturer tries to "catch up" on windows after standby

2021-12-08T08:22:54.729153Z  INFO timetrackrs::capture: sleeping 30s
2021-12-08T08:22:55.054840Z  INFO timetrackrs::capture: sleeping 30s
2021-12-08T08:22:55.376356Z  INFO timetrackrs::capture: sleeping 30s
2021-12-08T08:22:55.698564Z  INFO timetrackrs::capture: sleeping 30s
2021-12-08T08:22:56.023379Z  INFO timetrackrs::capture: sleeping 30s
2021-12-08T08:22:56.346919Z  INFO timetrackrs::capture: sleeping 30s
2021-12-08T08:22:56.674801Z  INFO timetrackrs::capture: sleeping 30s
2021-12-08T08:22:56.996284Z  INFO timetrackrs::capture: sleeping 30s
2021-12-08T08:22:57.321964Z  INFO timetrackrs::capture: sleeping 30s
2021-12-08T08:22:57.645941Z  INFO timetrackrs::capture: sleeping 30s
2021-12-08T08:22:57.969895Z  INFO timetrackrs::capture: sleeping 30s
2021-12-08T08:22:58.297271Z  INFO timetrackrs::capture: sleeping 30s
2021-12-08T08:22:58.627182Z  INFO timetrackrs::capture: sleeping 30s

where is the data stored? in the .local/timetrackr/*.sqlite files?

Hi maybe it's just me, but where is the data stored? is there an easy way to convert it to csv? I know it's not an efficient format, but it's easier for me to grasp (and then get an idea of wether this tool is as useful as it looks! great job)

(if the question is too noob, just say so, I can accept that a tool requires a certain level of knowledge to even use :) )

compile error in hashbrown

With the latest stable Rust version, I get this compilation error (tested in Windows and Linux, both the same error) :

   Compiling hashbrown v0.11.2
error[E0554]: `#![feature]` may not be used on the stable release channel
  --> /home/frank/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.11.2/src/lib.rs:15:5
   |
15 | /     feature(
16 | |         test,
17 | |         core_intrinsics,
18 | |         dropck_eyepatch,
...  |
24 | |         maybe_uninit_array_assume_init
25 | |     )
   | |_____^

For more information about this error, try `rustc --explain E0554`.
error: could not compile `hashbrown` due to previous error
warning: build failed, waiting for other jobs to finish...
error: failed to compile `timetrackrs v0.1.0 (/home/frank/tmp/timetrackrs)`, intermediate artifacts can be found at `/home/frank/tmp/timetrackrs/target`

With the nightly Rust version, I get this error:

   Compiling timetrackrs v0.1.0 (C:\tmp\timetrackrs)
GOTOOO
error: proc-macro derive panicked
  --> src\server\server.rs:18:10
   |
18 | #[derive(RustEmbed)]
   |          ^^^^^^^^^
   |
   = help: message: #[derive(RustEmbed)] folder 'C:\tmp\timetrackrs\frontend/dist/' does not exist. cwd: 'C:\tmp\timetrackrs'

warning: unused imports: `ffi::OsString`, `slice`
 --> src\capture\windows\winwins.rs:1:33
  |
1 | use std::{collections::HashMap, ffi::OsString, slice};
  |                                 ^^^^^^^^^^^^^  ^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

error[E0599]: no function or associated item named `get` found for struct `FrontendDistAssets` in the current scope
  --> src\server\server.rs:24:37
   |
20 | struct FrontendDistAssets;
   | -------------------------- function or associated item `get` not found for this
...
24 |     let asset = FrontendDistAssets::get(path).ok_or_else(warp::reject::not_found)?;
   |                                     ^^^ function or associated item not found in `FrontendDistAssets`
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following traits define an item `get`, perhaps you need to implement one of them:
           candidate #1: `SliceIndex`
           candidate #2: `Row`
           candidate #3: `RustEmbed`

For more information about this error, try `rustc --explain E0599`.
warning: `timetrackrs` (lib) generated 1 warning
error: failed to compile `timetrackrs v0.1.0 (C:\tmp\timetrackrs)`, intermediate artifacts can be found at `C:\tmp\timetrackrs\target`

Caused by:
  could not compile `timetrackrs` due to 2 previous errors; 1 warning emitted

But would be nice anyway if it would compile with the latest stable version.

Compile cross-platform binaries with GitHub Actions

Windows, Linux, and MacOS binaries should be built via GitHub Actions.

This should happen whenever a new tag is pushed (e.g. for releases with cargo release) and possibly also "nightly" (the newest commit on master, at most once per day)

Show a status tray icon

Show a icon in whatever the native system tray is on each platform, that at least shows that the program is running successfully, and allows opening the web UI with a click.

Later, further functionality could include:

  • a button to pause tracking for some duration for privacy
  • notifications / calls to action (e.g. detect uncategorized time, ask what the user was doing)

Fix the single event viewer

The single-event viewer should show a single event plus the derivation chain for all the tags that were applied so you can visually debug your rules. It did this in the past but I think it's not in a working state.

You should be able to reach the single-event viewer with the API call that gets all the event ids in a specific time range / time chunk

Build instructions

Heya, this looks really cool and promissing for a time tracker app! :)
Can you tell me how to build it? I am not quite sure and didn't find any build instructions.

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.