Skip to content

Commit 6a66672

Browse files
committed
feat: debug mode
1 parent 7815f2f commit 6a66672

File tree

5 files changed

+62
-36
lines changed

5 files changed

+62
-36
lines changed

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,10 @@ To remove the extension, execute:
3939
pip uninstall jupyterlab_wakatime
4040
```
4141

42-
The following content is generated with the template:
43-
44-
---
45-
4642
## Troubleshoot
4743

44+
If you don't see the plugin in https://wakatime.com/plugins/status, please enable `debug` setting and check both JupyterLab logs in terminal and `wakatime.log` file.
45+
4846
If you are seeing the frontend extension, but it is not working, check
4947
that the server extension is enabled:
5048

@@ -59,6 +57,10 @@ the frontend extension, check the frontend extension is installed:
5957
jupyter labextension list
6058
```
6159

60+
The following content is generated with the template:
61+
62+
---
63+
6264
## Contributing
6365

6466
### Development install

jupyterlab_wakatime/handlers.py

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class BeatData(TypedDict):
1818
filepath: str
1919
iswrite: bool
2020
timestamp: float
21+
debug: bool
2122

2223

2324
class BeatHandler(APIHandler):
@@ -40,27 +41,31 @@ async def post(self):
4041
cmd_args.extend(["--time", str(data["timestamp"])])
4142
if data["iswrite"]:
4243
cmd_args.append("--write")
44+
if data.get("debug"):
45+
cmd_args.append("--verbose")
4346
except:
44-
self.log.info("wakatime-cli " + shlex.join(cmd_args))
4547
return self.finish(json.dumps({"code": 400}))
46-
self.log.info("wakatime-cli " + shlex.join(cmd_args))
48+
if data.get("debug"):
49+
self.log.info("wakatime-cli " + shlex.join(cmd_args))
4750

4851
# Async subprocess is required for non-blocking access to return code
4952
# However, it's not supported on Windows
5053
# As a workaround, create a Popen instance and leave it alone
5154
if platform.system() == "Windows":
52-
subprocess.Popen([WAKATIME_CLI, *cmd_args])
53-
return self.finish(json.dumps({"code": 0}))
54-
55-
proc = await asyncio.create_subprocess_exec(
56-
WAKATIME_CLI,
57-
*cmd_args,
58-
"--log-to-stdout",
59-
"--verbose",
60-
stdout=asyncio.subprocess.PIPE,
61-
)
62-
stdout, _ = await proc.communicate()
63-
stdout = stdout.decode().strip()
55+
if not data.get("debug"):
56+
subprocess.Popen([WAKATIME_CLI, *cmd_args])
57+
return self.finish(json.dumps({"code": 0}))
58+
proc = subprocess.run([WAKATIME_CLI, *cmd_args], stdout=subprocess.PIPE)
59+
stdout = proc.stdout.decode().strip()
60+
else:
61+
proc = await asyncio.create_subprocess_exec(
62+
WAKATIME_CLI,
63+
*cmd_args,
64+
"--log-to-stdout",
65+
stdout=asyncio.subprocess.PIPE,
66+
)
67+
stdout, _ = await proc.communicate()
68+
stdout = stdout.decode().strip()
6469

6570
if proc.returncode == 112:
6671
self.log.warning("WakaTime rate limited")
@@ -77,9 +82,11 @@ async def post(self):
7782
for line in stdout.split("\n"):
7883
with suppress(json.JSONDecodeError):
7984
log = json.loads(line)
80-
if log.get("level") != "error":
81-
continue
82-
self.log.error("WakaTime error: %s", log.get("message", line))
85+
level = log.get("level", "")
86+
if hasattr(self.log, level):
87+
getattr(self.log, level)(
88+
"WakaTime %s: %s", level, log.get("message")
89+
)
8390
return self.finish(json.dumps({"code": proc.returncode}))
8491

8592

schema/plugin.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55
"jupyter.lab.setting-icon": "jupyterlab-wakatime:wakatime",
66
"type": "object",
77
"properties": {
8+
"debug": {
9+
"type": "boolean",
10+
"title": "Debug mode",
11+
"description": "Turn on debug mode.",
12+
"default": false
13+
},
814
"status": {
915
"type": "boolean",
1016
"title": "Show on status bar",

src/index.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { IEditorTracker } from '@jupyterlab/fileeditor'
44
import { ISettingRegistry } from '@jupyterlab/settingregistry'
55
import { IStatusBar } from '@jupyterlab/statusbar'
66

7-
import { createHeart, pollStatus } from './watch'
7+
import { Heart, pollStatus } from './watch'
88
import { StatusModel, WakaTimeStatus } from './status'
99

1010
/**
@@ -25,44 +25,46 @@ const plugin: JupyterFrontEndPlugin<void> = {
2525
) => {
2626
console.log('JupyterLab extension jupyterlab-wakatime is activated!')
2727
const statusModel = new StatusModel()
28-
const beatHeart = createHeart(statusModel)
28+
const heart = new Heart(statusModel)
2929

3030
notebooks.widgetAdded.connect((_, notebook) => {
3131
const filepath = notebook.sessionContext.path
3232
notebook.content.model?.contentChanged.connect(() => {
33-
beatHeart(filepath, 'change')
33+
heart.beat(filepath, 'change')
3434
})
3535
notebook.content.model?.stateChanged.connect((_, change) => {
3636
if (change.name === 'dirty' && change.oldValue) {
37-
beatHeart(filepath, 'write')
37+
heart.beat(filepath, 'write')
3838
}
3939
})
4040
})
4141
notebooks.currentChanged.connect((_, notebook) => {
42-
if (notebook === null) {
43-
return
42+
if (notebook !== null) {
43+
heart.beat(notebook.sessionContext.path, 'switch')
4444
}
45-
beatHeart(notebook.sessionContext.path, 'switch')
4645
})
4746
editors.widgetAdded.connect((_, editor) => {
4847
editor.context.fileChanged.connect(ctx => {
49-
beatHeart(ctx.path, 'change')
48+
heart.beat(ctx.path, 'change')
5049
})
5150
editor.context.saveState.connect((ctx, state) => {
5251
if (state === 'completed') {
53-
beatHeart(ctx.path, 'write')
52+
heart.beat(ctx.path, 'write')
5453
}
5554
})
5655
})
5756
editors.currentChanged.connect((_, editor) => {
5857
if (editor !== null) {
59-
beatHeart(editor.context.path, 'switch')
58+
heart.beat(editor.context.path, 'switch')
6059
}
6160
})
6261
if (settingRegistry) {
6362
settingRegistry
6463
.load(plugin.id)
6564
.then(settings => {
65+
if (settings.get('debug').composite) {
66+
heart.debug = true
67+
}
6668
if (settings.get('status').composite && statusBar) {
6769
const wakatimeStatus = new WakaTimeStatus(statusModel)
6870
statusBar.registerStatusItem('wakatime-status', {

src/watch.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,21 @@ export type BeatData = {
99
filepath: string
1010
timestamp: number
1111
iswrite: boolean
12+
debug: boolean
1213
}
1314

14-
export const createHeart = (statusModel: StatusModel) => {
15-
return async (
15+
export class Heart {
16+
statusModel: StatusModel
17+
debug: boolean
18+
19+
constructor(statusModel: StatusModel, debug: boolean = false) {
20+
this.statusModel = statusModel
21+
this.debug = debug
22+
}
23+
async beat(
1624
filepath: string,
1725
type: 'switch' | 'change' | 'write'
18-
) => {
26+
) {
1927
console.log(type, filepath)
2028
const now = Date.now()
2129
if (type === 'change' && now - lastBeat < wakaInterval) {
@@ -24,14 +32,15 @@ export const createHeart = (statusModel: StatusModel) => {
2432
const data: BeatData = {
2533
filepath: filepath,
2634
timestamp: now / 1e3,
27-
iswrite: type === 'write'
35+
iswrite: type === 'write',
36+
debug: this.debug,
2837
}
2938
lastBeat = now
3039
const { code } = await requestAPI<{ code: number }>('heartbeat', {
3140
body: JSON.stringify(data),
3241
method: 'POST'
3342
})
34-
statusModel.error = code
43+
this.statusModel.error = code
3544
}
3645
}
3746

0 commit comments

Comments
 (0)