Open simonsan opened 3 months ago
Thanks for reaching out, and I am flattered you are also watching gitoxide
coming along :).
pace
makes a great first impression, both GitHub and CLI help and it's clear it has received a lot of work, thought and love.
Currently I use Clockify but I am not happy at all, and it's the reason I also planned to eventually write a time-tracking tool that does it all better :).
pace
seems like a project I could rather contribute to, and it's definitely in my mind for when I finally could start such a task. It's probably just 2 to 3 years away 😅.
Unfortunately, I can't really test it out yet for a variety of reasons which I jolt down below. Please do know though that I am very interested, it just seems too early for me.
pace import -t clockify times.csv
).cargo test
or I didn't find it. I'd expect journey tests to protect what users everyday works, and lots of unit tests for the 'deal with time segments' part of the program. I also switch between timezones from time to time, that should not lead to incorrect behaviour.I also use it from my phone from time to time, but it would be acceptable to only use it on one machine at first. Having it sync across machines is a feature I'd pay for, along with a way to interact with data on a website. Self-hosting would of course be optimal, but such a tool if done right could be a product. Look at Clockify, and that's the 'best' I could find. They are so bad and steal my data, telemetry can't be opted out either. It's insane, to the point where I intentionally obfuscate messages because my time-tracker can't be trusted.
Let's leave this issue open, maybe you can ping me here once my issues above are somewhat addressed so I can try to switch 🙏. Please do keep going :).
Hey @Byron thanks for your early feedback! <3
- I would like to learn front and center on the project page how it stores (and keeps safe) my data. My timetracking data is important to me as it includes billable items, and loosing them is like loosing money. Seeing anything less than a real database (like SQLite) as storage backend wouldn't be good enough for me.
Yeah, I understand that, currently it uses a toml file as a storage, because for the beginning I found it easy to use and it could be edited in a text editor, which I found quite important as well, for some use cases. It is locally saved, can be backed up and archived, by e.g. renaming the file. Currently the standard name is activities.pace.toml
but I will implement an archiving functionality in the future.
Currently an entry in the log file looks like this:
[01HQXSQ6J231Q50MDPKGQ83CV9]
category = "Developer::Pace"
description = "Explain Piratricia pace"
begin = "2024-03-01T23:59:59"
end = "2024-03-02T16:07:55"
duration = 58076
kind = "activity"
tags = ["dev", "bla"]
status = "ended"
[01HQZRMCXDQZXDKTZSAFKW1JN0]
category = "Developer::Pace"
description = "Explain Piratricia pace"
begin = "2024-03-02T15:21:04"
end = "2024-03-02T16:06:52"
duration = 2748
kind = "intermission"
parent-id = "01HQXSQ6J231Q50MDPKGQ83CV9"
status = "ended"
I already chose a format that will make it easy to adopt the whole infrastructure to a database. As the activity data are already being parsed into a BTreeMap<ActivityGuid, Activity>
. The TomlFileStorage
is backed by an InMemoryStorage
, both implement the Storage
trait that will also be implemented for SQLiteStorage
. The advantage with the backing in Memory is, that I implemented the tests for InMemoryStorage
because that is what TomlFileStorage
essentially forwards all calls to.
- It should be easy to import existing data to be able to start evaluating with a backlog of real-world data. It's fine to support a pre-defined format and the user has to convert to the format themselves at first - alpha-users can do that, even though later one probably wants to implement importers for different sources to make this painless (i.e.
pace import -t clockify times.csv
).
Importing existing data is one thing, that is on the to-do list, for sure. Do you happen to have some recommendations, which formats you are having in mind? I'm thinking of abstracting that away behind an Importer
trait and people can also implement their own importers for the future, because importing is a never-ending task, I think? What would help you the most?
- It must be possible to export every bit of data. Simply having a SQLite database as backend would qualify already. No user should be locked-in, so this information should probably also be front-and-center on the project page.
Having a toml file, currently, fulfils this, I would say. That being said, it's super helpful, that you state what you want to read on the front page, because the current readme is the one I started out with to track currently implemented features and commands. So I will for sure adapt that in the near future, when I overwork the documentation for users and devs.
- The HTML templating engine to generate reports or summaries for predefined time ranges is a must for me, as I use this in my invoices.
Absolutely agreed 👍, it's definitely something I will implement rather sooner than later, because I see the need for that as well.
- Last but not least: tests, without tests I don't trust it's correct. It can't mess up the timesheets or invoices won't be correct. A glimpse at CI didn't reveal any
cargo test
or I didn't find it. I'd expect journey tests to protect what users everyday works, and lots of unit tests for the 'deal with time segments' part of the program. I also switch between timezones from time to time, that should not lead to incorrect behaviour.
Also agreed, I implemented nearly 100 tests to this day. Especially for dealing with the PaceDateTime
, PaceDuration
and PaceDate
/PaceTime
structs internally. I think you may have checked another CI run for docs, which doesn't run the full pipeline to save our planet's resources. The whole test run could be found here: https://github.com/pace-rs/pace/actions/runs/8198816654/job/22422935936#step:6:1
The current testing strategy involves unit tests for a lot of things, integration tests for the main services (ActivityTracker
and ActivityStore
backed by the InMemoryStorage
), snapshot tests for CLI related output. An example for a journey test is test_important_pace_flow_for_activities_passes
.
The current test coverage is: 49.03% coverage, 480/979 lines covered (by cargo tarpaulin)
, where I tried to choose the most significant one's for now, but I will definitely raise that more, to make sure that also edge cases are covered and not just the main functionality.
For timezone switching, I will certainly have to still implement things, currently I only work with chrono::Local
. So I will put that on the to-do list.
Hey @Byron thanks for your early feedback! <3
I am glad I could help a little.
- I would like to learn front and center on the project page how it stores (and keeps safe) my data. My timetracking data is important to me as it includes billable items, and loosing them is like loosing money. Seeing anything less than a real database (like SQLite) as storage backend wouldn't be good enough for me.
Yeah, I understand that, currently it uses a toml file as a storage, because for the beginning I found it easy to use and it could be edited in a text editor, which I found quite important as well, for some use cases. It is locally saved, can be backed up and archived, by e.g. renaming the file. Currently the standard name is
activities.pace.toml
but I will implement an archiving functionality in the future.
This looks like an append-only file format which has advantages, as at worst it could write garbage to the end of the file leaving it un-parseable. But that can be fixed by hand so it's not a total loss. Concurrency also isn't a problem with typical user interaction as these appends would be so fast it's hard to interleave them with multiple processes/concurrent writes.
Currently an entry in the log file looks like this:
[01HQXSQ6J231Q50MDPKGQ83CV9] category = "Developer::Pace" description = "Explain Piratricia pace" begin = "2024-03-01T23:59:59" end = "2024-03-02T16:07:55" duration = 58076 kind = "activity" tags = ["dev", "bla"] status = "ended" [01HQZRMCXDQZXDKTZSAFKW1JN0] category = "Developer::Pace" description = "Explain Piratricia pace" begin = "2024-03-02T15:21:04" end = "2024-03-02T16:06:52" duration = 2748 kind = "intermission" parent-id = "01HQXSQ6J231Q50MDPKGQ83CV9" status = "ended"
I already chose a format that will make it easy to adopt the whole infrastructure to a database. As the activity data are already being parsed into a
BTreeMap<ActivityGuid, Activity>
. TheTomlFileStorage
is backed by anInMemoryStorage
, both implement theStorage
trait that will also be implemented forSQLiteStorage
. The advantage with the backing in Memory is, that I implemented the tests forInMemoryStorage
because that is whatTomlFileStorage
essentially forwards all calls to.
I truly think that using SQLite here would help, for one as rock-solid data store and for users to feel they have control over their data by default. Tools exist to introspect SQLite database, for example, it's easy to export to other formats as well. It's a whole ecosystem that then comes for free.
- It should be easy to import existing data to be able to start evaluating with a backlog of real-world data. It's fine to support a pre-defined format and the user has to convert to the format themselves at first - alpha-users can do that, even though later one probably wants to implement importers for different sources to make this painless (i.e.
pace import -t clockify times.csv
).Importing existing data is one thing, that is on the to-do list, for sure. Do you happen to have some recommendations, which formats you are having in mind? I'm thinking of abstracting that away behind an
Importer
trait and people can also implement their own importers for the future, because importing is a never-ending task, I think? What would help you the most?
I think having a Rust API for it would be great! I can imagine contributing an implementation of such 'import module' for clockify then, should be easy enough.
- It must be possible to export every bit of data. Simply having a SQLite database as backend would qualify already. No user should be locked-in, so this information should probably also be front-and-center on the project page.
Having a toml file, currently, fulfils this, I would say. That being said, it's super helpful, that you state what you want to read on the front page, because the current readme is the one I started out with to track currently implemented features and commands. So I will for sure adapt that in the near future, when I overwork the documentation for users and devs.
Yes, I agree, a TOML file would qualify.
- The HTML templating engine to generate reports or summaries for predefined time ranges is a must for me, as I use this in my invoices.
Absolutely agreed 👍, it's definitely something I will implement rather sooner than later, because I see the need for that as well.
- Last but not least: tests, without tests I don't trust it's correct. It can't mess up the timesheets or invoices won't be correct. A glimpse at CI didn't reveal any
cargo test
or I didn't find it. I'd expect journey tests to protect what users everyday works, and lots of unit tests for the 'deal with time segments' part of the program. I also switch between timezones from time to time, that should not lead to incorrect behaviour.Also agreed, I implemented nearly 100 tests to this day. Especially for dealing with the
PaceDateTime
,PaceDuration
andPaceDate
/PaceTime
structs internally. I think you may have checked another CI run for docs, which doesn't run the full pipeline to save our planet's resources. The whole test run could be found here: https://github.com/pace-rs/pace/actions/runs/8198816654/job/22422935936#step:6:1The current testing strategy involves unit tests for a lot of things, integration tests for the main services (
ActivityTracker
andActivityStore
backed by theInMemoryStorage
), snapshot tests for CLI related output. An example for a journey test istest_important_pace_flow_for_activities_passes
.
It's great to hear I was just missing them (as in: didn't find them).
The current test coverage is:
49.03% coverage, 480/979 lines covered (by cargo tarpaulin)
, where I tried to choose the most significant one's for now, but I will definitely raise that more, to make sure that also edge cases are covered and not just the main functionality.
It's really interesting that you use code-coverage in Rust. It's something I don't do at all, but rather, depending on the task admittedly, write tests first. In other cases, higher up the abstraction level, it's usually just one or two tests as fence-poles for typical usage, knowing the the Rust type system probably has you covered. In any case and from the sound of it, you have tests at different levels and that's already what I needed :).
For timezone switching, I will certainly have to still implement things, currently I only work with
chrono::Local
. So I will put that on the to-do list.
❤️🙏
Hey Sebastian, fellow Berliner and
gitoxide
fan here :)I'm currently working on an activity tracking (and hopefully a future task, project, and time management tool) written in Rust. Some time ago, I was looking at your time sheets and found it impressive to have this level of transparency. For some future self-employment, I wanted to create a CLI activity tracking tool. It's called
pace
and is on crates.io:Currently, it's at the stage, where the base activity tracking and reporting is implemented (although I still need to implement the output to
csv
, which will come soon.json
output of a review summary is already supported).Some future vision for `pace` in short
- implement HTML templating for `review` so people can export their activity logs to their own (and a premade) HTML template and print it as pdf, also they could create bills for customers like that (additional functionality for billable activities would be as easy as adding a new optional struct field to the activity log) - create a `pace-server` after implementing logging to `SQLite` so people could use pace on different devices and essentially self-host - implement task and project management file based first, so pace would create a `projects.pace.toml` in a directory root and then people could create multiple `tasks.pace.toml` in lower directory hierarchies that reference the root `projects.pace.toml` to have hierarchical tasks for e.g. monorepositories - based on the implementation of `tasks` we can then add pomodoro and other workflows - Pomodoro requires a longer running process, so here it would be essential to implement a small GUI like `work-break` did, more like a notification pop-up that is able to handle the pomodoro sessions ![screenshot](https://github.com/Byron/byron/assets/14062932/7f4fd94e-ff2d-4c2c-b257-9bd4910af208) - afterwards it would be nice to expand support from individual use to team collaborationI wonder if you would be able to test
pace
a bit and give some feedback from your perspective and use cases, so I can improve it. I think that would be really valuable to me. As I wrote it for people like you (and me).Until then, and thank you for your work on
gitoxide
, Simon