Skip to content

Commit d9a3546

Browse files
authored
Merge pull request #41 from aws-asolidu/1.3-idle
Add sagemaker-idle-extension
2 parents 95a99f7 + f4c8f86 commit d9a3546

File tree

15 files changed

+654
-2
lines changed

15 files changed

+654
-2
lines changed

patched-vscode/build/gulpfile.extensions.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ const compilations = [
6161
'extensions/search-result/tsconfig.json',
6262
'extensions/simple-browser/tsconfig.json',
6363
'extensions/sagemaker-extension/tsconfig.json',
64+
'extensions/sagemaker-idle-extension/tsconfig.json',
6465
'extensions/tunnel-forwarding/tsconfig.json',
6566
'extensions/typescript-language-features/test-workspace/tsconfig.json',
6667
'extensions/typescript-language-features/web/tsconfig.json',

patched-vscode/build/npm/dirs.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const dirs = [
4040
'extensions/php-language-features',
4141
'extensions/references-view',
4242
'extensions/sagemaker-extension',
43+
'extensions/sagemaker-idle-extension',
4344
'extensions/search-result',
4445
'extensions/simple-browser',
4546
'extensions/tunnel-forwarding',
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
.vscode/**
2+
.vscode-test/**
3+
out/test/**
4+
out/**
5+
test/**
6+
src/**
7+
tsconfig.json
8+
out/test/**
9+
out/**
10+
cgmanifest.json
11+
yarn.lock
12+
preview-src/**
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Contributing to the Sagemaker Idle Extension
2+
This guide explains how to make changes to this extension and test them.
3+
## How to Make Changes
4+
Changes to the sagemaker-idle-extension are managed by creating patches using the Quilt tool. Follow these steps:
5+
1. Create a new patch:
6+
```
7+
quilt new sagemaker-idle-extension-v<n>.patch # Replace <n> with the next version number
8+
```
9+
2. Make changes and add file
10+
```
11+
quilt add sagemaker-idle-extension-v<n>.patch
12+
```
13+
3. Refresh the patch to include your changes:
14+
```
15+
quilt refresh
16+
```
17+
4. Update the changes in the patched-vsode folder
18+
5. Commit your changes and submit a pull request from your personal fork.
19+
20+
## How to Test
21+
1. Launch the Extension with Code Editor in local environment:
22+
1. Install Prerequisite tools described [here](https://web.archive.org/web/20231012223533/https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites) for your operating system.
23+
2. Run sh ./scripts/install.sh
24+
3. Run yarn watch from within the vscode folder
25+
4. Open a new terminal and run ./vscode/scripts/code-server.sh --launch
26+
27+
2. Perform user activity such as file changes, cursor editor movements, and terminal activity
28+
3. Verify `lastActiveTimestamp` is updated in the `.sagemaker-last-active-timestamp` file.
29+
4. Verify that the `/api/idle` endpoint returns the same `lastActiveTimestamp.
30+
31+
### Test Cases
32+
1. File change Detectcion
33+
- Modify a file and ensure the timestamp updates.
34+
- Delete a file and verify the timestamp updates.
35+
2. Text Editor Movement
36+
- Move the text cursor within a file and check for timestamp updates.
37+
- Switch between files and verify updates.
38+
3. Terminal Activity
39+
- Open a new terminal, run a command, and ensure the timestamp updates.
40+
- Close the terminal and verify updates.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Code Editor Idle Extension
2+
3+
The Code Editor Idle Extension tracks user activity and logs the last active timestamp (in UTC) to a local file. User activities monitored include file changes, text editor selection changes, and terminal interactions. Additionally, it provides an API endpoint `/api/idle` that returns the lastActiveTimestamp.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright Amazon.com Inc. or its affiliates. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
//@ts-check
7+
8+
'use strict';
9+
10+
const withBrowserDefaults = require('../shared.webpack.config').browser;
11+
12+
module.exports = withBrowserDefaults({
13+
context: __dirname,
14+
entry: {
15+
extension: './src/extension.ts'
16+
},
17+
});
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright Amazon.com Inc. or its affiliates. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
//@ts-check
7+
8+
'use strict';
9+
10+
const withDefaults = require('../shared.webpack.config');
11+
12+
module.exports = withDefaults({
13+
context: __dirname,
14+
resolve: {
15+
mainFields: ['module', 'main']
16+
},
17+
entry: {
18+
extension: './src/extension.ts',
19+
}
20+
});
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"name": "sagemaker-idle-extension",
3+
"displayName": "Sagemaker Idle Extension",
4+
"description": "Expose an API called /idle that returns latest activity timestamp",
5+
"extensionKind": [
6+
"workspace"
7+
],
8+
"version": "1.0.0",
9+
"publisher": "sagemaker",
10+
"license": "MIT",
11+
"engines": {
12+
"vscode": "^1.70.0"
13+
},
14+
"main": "./out/extension",
15+
"categories": [
16+
"Other"
17+
],
18+
"activationEvents": [
19+
"*"
20+
],
21+
"capabilities": {
22+
"virtualWorkspaces": true,
23+
"untrustedWorkspaces": {
24+
"supported": true
25+
}
26+
},
27+
"contributes": {
28+
"configuration": {
29+
"type": "object",
30+
"title": "Sagemaker Idle Extension",
31+
"properties": {}
32+
},
33+
"commands": []
34+
},
35+
"scripts": {
36+
"compile": "gulp compile-extension:sagemaker-idle-extension",
37+
"watch": "npm run build-preview && gulp watch-extension:sagemaker-idle-extension",
38+
"vscode:prepublish": "npm run build-ext",
39+
"build-ext": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:sagemaker-idle-extension ./tsconfig.json"
40+
},
41+
"dependencies": {},
42+
"repository": {}
43+
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import * as vscode from "vscode";
2+
import * as fs from "fs";
3+
import * as path from "path";
4+
5+
let idleFilePath: string
6+
let terminalActivityInterval: NodeJS.Timeout | undefined
7+
const LOG_PREFIX = "[sagemaker-idle-extension]"
8+
const CHECK_INTERVAL = 60000; // 60 seconds interval
9+
10+
export function activate(context: vscode.ExtensionContext) {
11+
initializeIdleFilePath();
12+
registerEventListeners(context);
13+
startMonitoringTerminalActivity();
14+
}
15+
16+
export function deactivate() {
17+
if(terminalActivityInterval) {
18+
clearInterval(terminalActivityInterval)
19+
}
20+
}
21+
22+
/**
23+
* Initializes the file path where the idle timestamp will be stored.
24+
* It sets the path to a hidden file in the user's home directory.
25+
*/
26+
function initializeIdleFilePath() {
27+
const homeDirectory = process.env.HOME || process.env.USERPROFILE;
28+
if (!homeDirectory) {
29+
console.log(`${LOG_PREFIX} Unable to determine the home directory.`);
30+
return;
31+
}
32+
idleFilePath = path.join(homeDirectory, ".sagemaker-last-active-timestamp");
33+
34+
// Set initial lastActivetimestamp
35+
updateLastActivityTimestamp()
36+
}
37+
38+
/**
39+
* Registers event listeners to monitor user activity within the VSCode editor.
40+
* It listens to document changes, editor focus changes, text selection changes, and terminal events.
41+
* @param context - The context in which the extension is running.
42+
*/
43+
function registerEventListeners(context: vscode.ExtensionContext) {
44+
context.subscriptions.push(
45+
vscode.workspace.onDidChangeTextDocument((_) => {
46+
updateLastActivityTimestamp();
47+
}),
48+
vscode.window.onDidChangeActiveTextEditor((_) => {
49+
updateLastActivityTimestamp();
50+
}),
51+
vscode.window.onDidChangeTextEditorSelection((_) => {
52+
updateLastActivityTimestamp();
53+
}),
54+
vscode.window.onDidOpenTerminal((_) => {
55+
updateLastActivityTimestamp();
56+
}),
57+
vscode.window.onDidCloseTerminal((_) => {
58+
updateLastActivityTimestamp();
59+
})
60+
);
61+
}
62+
63+
/**
64+
* Starts monitoring terminal activity by setting an interval to check for activity in the /dev/pts directory.
65+
*/
66+
const startMonitoringTerminalActivity = () => {
67+
terminalActivityInterval = setInterval(checkTerminalActivity, CHECK_INTERVAL);
68+
};
69+
70+
71+
/**
72+
* Checks for terminal activity by reading the /dev/pts directory and comparing modification times of the files.
73+
*
74+
* The /dev/pts directory is used in Unix-like operating systems to represent pseudo-terminal (PTY) devices.
75+
* Each active terminal session is assigned a PTY device. These devices are represented as files within the /dev/pts directory.
76+
* When a terminal session has activity, such as when a user inputs commands or output is written to the terminal,
77+
* the modification time (mtime) of the corresponding PTY device file is updated. By monitoring the modification
78+
* times of the files in the /dev/pts directory, we can detect terminal activity.
79+
*
80+
* If activity is detected (i.e., if any PTY device file was modified within the CHECK_INTERVAL), this function
81+
* updates the last activity timestamp.
82+
*/
83+
const checkTerminalActivity = () => {
84+
fs.readdir("/dev/pts", (err, files) => {
85+
if (err) {
86+
console.error(`${LOG_PREFIX} Error reading /dev/pts directory:`, err);
87+
return;
88+
}
89+
90+
const now = Date.now();
91+
const activityDetected = files.some((file) => {
92+
const filePath = path.join("/dev/pts", file);
93+
try {
94+
const stats = fs.statSync(filePath);
95+
const mtime = new Date(stats.mtime).getTime();
96+
return now - mtime < CHECK_INTERVAL;
97+
} catch (error) {
98+
console.error(`${LOG_PREFIX}}Error reading file stats:`, error);
99+
return false;
100+
}
101+
});
102+
103+
if (activityDetected) {
104+
updateLastActivityTimestamp();
105+
}
106+
});
107+
};
108+
109+
/**
110+
* Updates the last activity timestamp by recording the current timestamp in the idle file and
111+
* refreshing the status bar. The timestamp should be in ISO 8601 format and set to the UTC timezone.
112+
*/
113+
function updateLastActivityTimestamp() {
114+
const timestamp = new Date().toISOString();
115+
fs.writeFileSync(idleFilePath, timestamp);
116+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"extends": "../tsconfig.base.json",
3+
"compilerOptions": {
4+
"outDir": "./out"
5+
},
6+
"include": [
7+
"../sagemaker-idle-extension/src/**/*",
8+
"../../src/vscode-dts/vscode.d.ts"
9+
]
10+
}

0 commit comments

Comments
 (0)