New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Creating a new watcher #131
Comments
There's a small code-example in the docs: https://activitywatch.readthedocs.io/en/latest/writing-watchers.html Just ask if you have any questions or issues adapting that code to your needs 🙂 |
Thanks much ! That raised a bunch of points : Slapping an import section on top of it would help.
Still, What I used personally is
The
Why does the |
Great questions, the docs certainly needs further explanation. Will update shortly!
Will fix!
The reason we have --testing is because while we are developing we are not sure that the data is correct until properly tested and verified, and you can run a stable and development version simultaneously on the non-testing and testing instances of aw-server simultaneously. Also if you for example would want to rewrite some part of your client but you're not sure that the code would be correct, it is easy to just connect with --testing instead so you don't need to worry about inserting some corrupt events into your bucket. We want people to be aware of this feature when developing so they don't accidentally put corrupt data in their buckets. I personally have months of data but only do backups approx. once a month, and I would become rather sad if i inserted corrupt data and had to revert weeks of data. We should probably make it easier later to remove select events from buckets from the aw-core library, but it is currently only possible to delete a whole bucket.
It is just an arbitrary label, but we use it so clients which do visualizations (e.g. aw-webui) and are looking for a specific type of events know what type of events each bucket contains. You can call it what you want as long as it is descriptive. If you collect multiple types of events in one client I would recommend making multiple buckets (I would guess that you don't though). We should probably enforce (or atleast recommend) lowercase and replace spaces with underscores or something just to keep consistency for all types. We should make it clear that it is not a description but an actual value which others use as a reference so people don't use whitespaces.
The reason why create_bucket is not queued is in case the create_bucket request fails to aw-server a exception should occur. The queue is not blocking so it doesn't raise any exceptions if some request fails, it just queues up the events and re-tries every X seconds. |
It also seems like the client.connect() call is missing in that example client, so no queued events will be saved it seems. There's apparently also a second example in ActivityWatch/docs/examples/client.py which looks better though so you should probably have a look at that instead. Will fix this code duplication. |
Fair enough ! :) (then all I'm saying is I (n=1) find it easier to use the main server as testing)
Sounds to me like more rules than are necessary. A convention for knowledgeable devs, sure, but please please keep it simple = accessible for us newcomers. You can always
Doesn't matter much, but I don't get this part. You just said I could call it what I wanted, so why not allow tl;dr : I suggest making the doc
It's pretty suggestive and shows the kind of values that are accepted.
Hrm, okay, then why is it True in the doc example ? Anyway this seems like it'll get nuked/rewritten so I'll wait until it's better. |
Re the second example, I find the first one gets a few points better :
The end of the example ( |
Two specific questions about the code and current status of my solution :
Now my watcher works with Using
(EDIT : I know it says it's the create_bucket line that raises the error but the same line worked when using insert_event instead of heartbeats, so I don't know if it's related or just a coincidence, but I report what I see and I meant exactly what I wrote :p) While the aw-qt console says :
|
It isn't client.heartbeat which fails but client.create_bucket, look at the last line here
run aw-server with --verbose and you will see more info and it will likely say what's wrong with the request Will update the docs soon with a new example with more comments |
Was able to reproduce your create_bucket failing, aw-server was responding with a 400 status code instead of a 304, fixed here ActivityWatch/aw-server@7f424fb It apparently worked because we run create_bucket asyncronously in all of our watchers so the exception wasn't raised there. Tested with the example watcher, works syncronously now aswell :) |
The example in the docs is now update, will take a few hours until it's updated but you can look directly at the source. I think i adressed most of your concerns, tell me if I missed something. |
I've had the idea of using a namespace for these types. For example would "currentwindow" become "org.activitywatch.window.active". I've written about it here in the past: #97 @nikanar Thanks for all the feedback, if you have the time you can create a PR or if not I'll keep the things you've said in mind when editing.
Nice bug catching @nikanar and nice fix @johan-bjareholt. |
I already fixed this and added both a minimal 20-line example as well as a very extensively commented ~80-line client. There are a few more things which needs documentation though.
|
Thanks @johan-bjareholt the new examples are great. Minor nitpick, the long example also doesn't use the Sorry for taking so long to update, I'm still having a hard time with git-maintaining
Most definitely. It's an important feature you got that most users aren't familiar with, and it gets in the way every time we want to dive in the internals, as iiuc you expect some part of the community to do.
|
Currently all I can get at is:
aw-qt's terminal says My code does:
I don't know if I failed to get the latest version of |
Yup, looks like you aren't running the latest Regardless, I will update the
I can add a flag to the Makefiles to make life easier for you 🙂
|
To be certain, do |
Indeed @ErikBjare that was it. Omg, The watcher works now ! It stores data which is visible in the webui. Identical consecutive events are merged together. The
Time for me to move on to visualising that bucket ! |
@nikanar Awesome! Great to see you got it working 😄 Huge thanks for helping us make the process a bit less cumbersome for people in the future. I updated the doc to mention the Closing this for now, but don't hesitate to let us know how things turn out 🚀 |
Update : Turns out, of course, the watcher watches even when I'm afk. So stats about raw watched data aren't too meaningful, and I have to throw afk-watcher observations into the mix to do something useful. It's about done now, but my conclusion is that I should have included the afk-watcher Hopefully this can help others to not run in the same issue. Gory data detailsI also have 30 'not-afk' events with 0 duration, out of 1200 afk-watcher events (53% not-afk so they must not be perfectly alternating), which I'm ignoring. In fact I filter out all events of 0 duration.I also ran into issues like
where "ak" stands for "not-afk". But I think it's on my side because my watcher was running but not aw-watcher-afk because aw-qt was crashed at that time but not aw-server because ActivityWatch/aw-server#31. There aren't too many of these, and in particular none is recent. |
This is not the way we hope people will implement watchers. As you might know the window watcher solves this without including that in its 'data' field and does so by doing transformations in aw-server which cuts portion of events where there is no 'not-afk' intersecting it. Currently in AW 0.7 we do that with a kind of query language in JSON format, but that will soon be deprecated since we were not satisfied with the API. However it will be replaced by my dev/transform-next pull requests which will specify an actual nice looking query language for clients to request transforms on data from multiple buckets from the aw-server. In the end we hope that the watchers will just push their single data point in lossless format to a aw-server bucket and then when displaying it we can aggregate and transform data from multiple buckets with this query language in a format which fits how we want to visualize the data.
We have an issue on this and it's high priority, I am on holidays now so hopefully I'll have some time to get around and reproduce+fix this soon. |
Hrm, oh wow, I had no idea. From here, this all sounds like documentation waiting to exist ;) So iiuc you want pure raw data in the buckets, and preprocessing to be done "by users" (at least the watcher-writing ones) in your query language ? If so, ok, why not, I only hope you'll implement nice doc and default values for this part. This sounds a bit at odds with hibernating events not being reported anymore since ActivityWatch/aw-watcher-afk#26 ? I would expect this view to imply the afk-watcher must push all the datapoints it can. |
This should fix at least some of the aw-watcher-afk issues I believe ActivityWatch/aw-watcher-afk#31
In progress :) ActivityWatch/docs#2
Well you can with the old query API, but since it will be deprecated soon and it's not documented i recommend not wasting your time on it! If you still want to get it done soon I would appreciate if you tested the dev/transform-next branches (which also includes some other goodies like aw-watcher-web domain summaries).
Well not "by users", but by each program which visualizes activitywatch data (primarily aw-webui).
I actually still run the old aw-watcher-afk commit with hibernation support on one of my computers and it's all backwards compatible so it still works. The only reason we removed it was since there seemed to be some corner case where it overlapped other events so we removed it. We will likely add it back later, but that's currently not a priority. |
@nikanar Hey! I'm looking for something similar to what your are working/worked on. Did you publish your code in a public repository? |
@rhabbachi Not that I can remember. I think it boils down to the following
... given that the window manager (awesome-wm) writes in
and then calling that function whenever I change tags (by whatever keybinding or clicking sequence) = user input changes the observed value - e.g.
There, now it's done :') |
Hey @nikata, Thanks for the code and the tips!
--
*Riadh Habbachi*
*Principal ConsultantRDH Consulting*
E: habbachi.riadh@gmail.com
M: +216 92 614 041
…On Wed, Sep 12, 2018 at 8:42 PM Nikana ***@***.***> wrote:
@rhabbachi <https://github.com/rhabbachi> Not that I can remember. I
think it boils down to the following
***@***.***:~$ cat .../AW/aw-wmtag.py
#!/usr/bin/python3
import subprocess
import time, datetime
from aw_client import ActivityWatchClient
from aw_core.models import Event
def main():
client = ActivityWatchClient("aw-wmtag")
bucket_id = "{}_{}".format(client.name, client.hostname) # Give your bucket a unique id.
event_type = "activedesktop" # Used to annotate what kind of data the events in a given bucket will contain.
client.create_bucket(bucket_id, event_type)
poll_time = 5 # Send an event every 5 seconds
with client:
while True:
data = {"desktop": get_the_watched_thing()}
now = datetime.datetime.now(datetime.timezone.utc)
awesome_event = Event(timestamp=now, data=data)
client.heartbeat(bucket_id, awesome_event, pulsetime=poll_time+1, queued=True)
time.sleep(poll_time)
def get_the_watched_thing():
filename = "/path/to/awesome-logging.log"
f = subprocess.Popen(['tail','-c','2',filename],
stdout=subprocess.PIPE,stderr=subprocess.PIPE)
value = int(f.stdout.read(1))
# print("Looking at {} says desktop is currently {}".format(filename, value))
return value
if __name__ == "__main__":
main()
... given that the window manager (awesome-wm) writes in
/path/to/awesome-logging.log, with the following (excerpt from
~/.config/awesome/rc.lua):
local function log_current_tag()
local i = awful.screen.focused().selected_tag.index
file = io.open("/path/to/awesome-logging.log", "a")
file:write(string.format("%s Switching to awesome tag %i\n", os.date("%Y/%m/%d %X"), i))
file:close()
end
and then calling that function whenever I change tags (by whatever
keybinding or clicking sequence) = user input changes the observed value -
e.g.
awful.key({modkey}, "Tab", function () awful.tag.viewnext() log_current_tag() end),
There, now it's done :')
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#131 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AB01wrdjreJSgfddhBbh7UC9OkI1CqVfks5uaWOpgaJpZM4QXz5c>
.
|
I would like to watch one integer variable from my window-manager (XY context : the virtual desktop I am in, as they are a good classification of the activities I do on the computer + makes it trivial to label current activity, by just moving to the corresponding space).
What would be a bare-bones watcher ?
Only has to run on linux. I can have the watched-thing run a shell command (messaging the watcher) every time its value changes, so it doesn't even have to continuously listen (though if it must listen, it can watch the
/tmp/current-value
file, easy).The text was updated successfully, but these errors were encountered: