Firstly, thank you for your interest in contributing to Extension Activity Monitor. Your contribution will make this project more awesome. 🚀
- Project Architecture
- Picking an issue
- Installation
- Writing and Running Tests
- Checking for Linter
- Checking for Prettier
- Submitting a Bug or Issue or Feature Request
- Creating a Pull Request
The Extension Activity Monitor is composed of a backend responsible for the collection and storage of the activity logs (in the background page), and a frontend to allow the user to manage the log collection and view the logs (browserAction popup and an extension tab/devtools panel).
The background page acts as the backend of the extension, and the core of it is implemented in ext-monitor.js
. This part is responsible for keeping track of activity logs and monitored extensions on behalf of the frontend. The background page subscribes to the runtime.onMessage
event to listen for messages from the Popup and Activity Log pages.
The browserAction popup is a control panel to trigger "start monitoring" and "stop monitoring" (of extensions) and opening the Activity Log page.
The Activity Log page is the frontend tasked with rendering the log information from the backend. It uses the MVC architecture and web components for the table view and filtering options.
-
The Model class stores activity logs being rendered in the activity log page and the data representation of the log filters. The Model class also provides the
matchLogWithFilterObj
method to check if a particular log entry does match the filters. -
The View class manages the
log-view
and filters web components. The log-view webcomponent is responsible for rendering the collected logs (currently in a table form) and managing the log-view context menu. The filters web components are responsible for the UI elements related to the log filters. -
The Controller class interacts with the backend and ensures that the Model and View are synchronized.
This page can be accessed via "Extension Activity" panel in devtools. The "Extension Activity" devtools panel contains an instance of the Activity Log page where every real-time activity log collected is automatically filtered by the current tab id. The devtools panel retrieves the tab id filter from the devtools panel url search params, set by the devtools page by retrieving it using browser.devtools.inspectedWindow.tabId
when the devtools panel is being registered.
The extension receives each activity log in the form of an object
from activityLog API. The activityLog API schema can be found here.
When the Activity Log page is opened via the popup, it fetches the existing logs (if logs were collected before) from the backend. While the Activity Log page is opened, it receives real-time logs from the backend and renders them. It can send instructions to the background page via runtime.sendMessage
API to save logs to a JSON file, load logs from JSON file and clear logs.
-
The backend subscribes to the
browser.activityLog.onExtensionActivity
API event to receive objects that describe the activity of the monitored extensions. While the monitor is active, any newly installed extension will be monitored automatically.The real-time logs are collected in the background page and sent to Activity Log page while it is opened. Activity logs are sent from the backend via the
sendLogs
method. The Activity Log page listens for logs viaruntime.onMessage
event and render those in thelog-view
.The logs are kept in the background page unless it receives the
clearlogs
instruction from Activity Log page. The background page also sends the real-time logs to Activity Log page. -
Live logs can be saved by exporting the collected logs as JSON, via
saveLogs
instruction fromsave-load.js
. Previously saved logs can be loaded via loading a JSON file, which opens an instance of Activity Log page in a new tab loaded with logs from the JSON file. Note that this instance of Activity Log page doesn't receive real-time logs (as it doesn't subscribe tobrowser.runtime.onMessage
event listener to receive real-time logs).
The logs are rendered using the log-view
web component. Any new log that doesn't match the filters will be hidden.
Individual log items can be hidden by user-defined filters. These filters are stored in the Model of the Activity Log page. A JSDoc explaining the filter object can be found here. The Model is updated when the controller is notified of filter changes via onFilterChanged
. Ultimately, the log-view
hides the table rows that didn't match the applied filters. The filters can be changed by the user via the following UI components:
filter-option
provides the UI to filter by individual properties of log entries (such as extension id, view type, API name, API type). The available filter values are derived from the logs collected so far. During live logging, new unknown filter values may appear and be appended to the filter UI.filter-keyword
provides the UI to filter by substring. It searches the provided substring inside thedata
property of the log object.filter-timestamp
provides the UI to filter by timestamps. The timestamps filter can be applied by choosing "start time" or "stop time" or both (from the context menu) to hide the logs that don't fall under the chosen timestamp range.
When the Activity Log page is opened through the devtools panel, logs will be filtered by that tab's id. This filter cannot be changed through the UI.
If you are a new contributor looking for a easy bug/issue to get started, take a look at the list of good first bugs. Feel free to ask permission from the maintainers by commenting on any issue that you would like to work on.
To install Extension Activity Monitor, follow the given instructions here.
Tests are stored in the tests directory and run with the Jest framework.
To run all the tests once, run the following command:
$ npm test
To run a single test once, run the following command:
$ npm test ext-monitor.test.js
Here, ext-monitor.test.js
is the name of the test file.
To run all the tests on file changes during development, run the following command:
$ npm run test:watch
To get the coverage report of all the tests, run the following command:
$ npm run test:coverage
This project is using ESLint as linter. To make sure your code is compatible with our lint check, run the following command:
$ npm run lint:check
To make ESLint try to fix the lint errors automatically, run the following command:
$ npm run lint:fix
This project is using Prettier as code formatter. To make sure your code is formatted correctly, run the following code:
$ npm run prettier:check
To make Prettier try to fix the code formatting errors automatically, run the following command:
$ npm run prettier:fix
NOTE: Both ESLint and Prettier ignores the path mentioned in .gitignore
file.
If you find a bug/issue in the codes or want to request a feature, you can help us by submitting an issue to our GitHub Repository. Feel free ask for permission from the maintainers of the repository if you want to work on the filed issue.
When you create a pull request for an issue or new feature, be sure to mention the issue number for what you're working on. The best way to do it is to mention the issue like this at the top of the PR's description:
Fixes #123
The issue number in this case is "123." The word "Fixes" will automatically close the issue when your pull request is merged.
We write the commit message in conventional way stated in Conventional Commits Specification to generate change changelog without too much noise. Use past tense to write commit message. Your commit should be any of the following types:
feat: Add a new feature
fix: Fix a Bug or Issue
docs: Improve contributing docs
style: Add comments or formatted code etc.
refactor: Split out or re-arranging codes that doesn't change the functionalities
perf: Improve performance of any functionality
test: Add test for new or existing features
chore: Changes in the build process, upgrading dependencies etc.