Skip to content

Commit

Permalink
Dev/1.2.0 (#21)
Browse files Browse the repository at this point in the history
* feat: move version into footer

* fix: different analytics categories for matcher types

* feat: context menu search selection
  • Loading branch information
Artboomy authored Mar 9, 2024
1 parent 0adef73 commit 01ad5f7
Show file tree
Hide file tree
Showing 15 changed files with 144 additions and 53 deletions.
60 changes: 30 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,12 @@ This is extendable network request viewer extension for Chromium-based browsers.

The extension will appear in devtools as a `📜 Net logs` tab.

* 🔍 **Search:** Filter by url and search by params/result.
* 🎨 Presets: GraphQL & JSON-RPC protocols unpacking.
* ⛰️ **Integration:** View Next.js & NuxtJS hydration state.
* 🛠️ **Customization:** Transform name, parameters, and response with javascript.
***Universality:** View live logs or load
from [`*.har` file](https://developer.chrome.com/docs/devtools/network/reference/#save-as-har).
* 🤝 **Team-oriented:** Export logs and share them with others.
* 🔍 **Advanced Search**: Filter requests by URL and search within parameters/results.
* ⛰️ **Framework Integration**: View Next.js & NuxtJS hydration state.
* 🎨 **Protocol Presets**: Streamlined unpacking for GraphQL and JSON-RPC.
* 🛠️ **Customization**: Modify request names, parameters, and responses with JavaScript.
***Log Viewing**: Analyze live or import logs from HAR/*.netlogs.zip files.
* 🤝 **Collaboration**: Export and share logs for team debugging.

![main.gif](./img/main.gif)

Expand Down Expand Up @@ -94,40 +93,40 @@ Event signature is either `IItemContentOnlyCfg`:

```typescript
type IItemContentOnlyCfg = {
// by default new Date().getTime() will be used
timestamp?: number;
// small bit of text next to date
tag?: string;
// viewable on date click
meta?: {
key: {
items: [{ name: string, value: string }]
// by default new Date().getTime() will be used
timestamp?: number;
// small bit of text next to date
tag?: string;
// viewable on date click
meta?: {
key: {
items: [{ name: string, value: string }]
}
}
}

content: object | string;
content: object | string;
}
```
or `IItemTransactionCfg`
```typescript
type IItemTransactionCfg = {
// by default new Date().getTime() will be used
timestamp?: number;
// small bit of text next to date
tag?: string;
name?: string;
// viewable on date click
meta?: {
key: {
items: [{ name: string, value: string }]
// by default new Date().getTime() will be used
timestamp?: number;
// small bit of text next to date
tag?: string;
name?: string;
// viewable on date click
meta?: {
key: {
items: [{ name: string, value: string }]
}
}
}

params: object;
params: object;

result: object;
result: object;
}
```
Expand Down Expand Up @@ -166,7 +165,8 @@ All settings are stored locally.
## 🤝 Permissions
* `storage` - used to store your custom settings. Does not sync.
* `content_scripts` - used to extract nextjs/nuxtjs data from page.
* `content_scripts` - used to extract Nextjs/Nuxtjs data from page.
* `contextMenus` - used to extract selected text for search
The list may extend in the future.
Expand Down
9 changes: 7 additions & 2 deletions dist/manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Net logs",
"version": "1.1.0",
"version": "1.2.0",
"manifest_version": 3,
"minimum_chrome_version": "88",
"description": "Extendable network logs debugger",
Expand All @@ -12,8 +12,13 @@
"128": "icons/128.png"
},
"permissions": [
"storage"
"storage",
"contextMenus"
],
"background": {
"service_worker": "js/background.js",
"type": "module"
},
"sandbox": {
"pages": [
"sandbox.html",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "netlogs",
"version": "1.1.0",
"version": "1.2.0",
"description": "Web extension for custom network logs representation",
"main": "index.js",
"author": "artboomy",
Expand Down
7 changes: 4 additions & 3 deletions src/api/analytics.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import Error = chrome.cast.Error;

const GA_ENDPOINT = 'https://www.google-analytics.com/mp/collect';
const GA_DEBUG_ENDPOINT = 'https://www.google-analytics.com/debug/mp/collect';
import secrets from '../secrets.json';
Expand Down Expand Up @@ -125,7 +123,10 @@ class Analytics {
}

// Fire an error event.
async fireErrorEvent(error: Error, additionalParams: Params = {}) {
async fireErrorEvent(
error: chrome.cast.Error | Error,
additionalParams: Params = {}
) {
// Note: 'error' is a reserved event name and cannot be used
// see https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference?client_type=gtag#reserved_names
return this.fireEvent('extension_error', {
Expand Down
2 changes: 1 addition & 1 deletion src/api/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class SandboxRuntime {
return {
manifest_version: 3,
name: 'Net logs',
version: '1.1.0'
version: '1.2.0'
};
}

Expand Down
9 changes: 9 additions & 0 deletions src/app/panel.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { wrapSandbox } from '../sandboxUtils';
import { createEventPayload, isExtension, postSandbox } from '../utils';
import analytics from '../api/analytics';
import Port = chrome.runtime.Port;

const tabId = isExtension() && window.chrome.devtools.inspectedWindow.tabId;
Expand All @@ -24,6 +25,14 @@ const messageHandler = (
if (tabId === port.sender?.tab?.id) {
if (type === 'fromContent') {
postSandbox(createEventPayload('newItem', e.data));
try {
const d = JSON.parse(e.data);
if (!['NEXT', 'NUXT'].includes(d.tag)) {
analytics.fireEvent('customEvent');
}
} catch (_e) {
// pass
}
}
}
};
Expand Down
11 changes: 9 additions & 2 deletions src/components/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { Component } from 'react';
import { ErrorInfo } from 'react';
import React, { Component, ErrorInfo } from 'react';
import { callParentVoid } from '../utils';

type TState = { hasError: boolean; error: Error | null };
export default class ErrorBoundary extends Component<
Expand All @@ -22,6 +22,13 @@ export default class ErrorBoundary extends Component<
'A following error occurred. This may indicate problems with custom functions or bug in the extension'
);
console.error(error, errorInfo);
callParentVoid(
'analytics.error',
JSON.stringify({
message: error.message,
stack: errorInfo.componentStack
})
);
}

render(): React.ReactNode {
Expand Down
7 changes: 7 additions & 0 deletions src/components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { TagList } from './TagList';
import { useSettings } from '../hooks/useSettings';
import { useListStore } from '../controllers/network';
import { Link } from './Link';
import runtime from '../api/runtime';

const useStyles = createUseStyles({
root: {
Expand All @@ -21,6 +22,10 @@ const useStyles = createUseStyles({
countWrapper: {
marginLeft: '8px',
marginRight: 'auto'
},
version: {
fontStyle: 'italic',
paddingRight: '4px'
}
});
export const Footer: FC<{
Expand All @@ -30,6 +35,7 @@ export const Footer: FC<{
totalCount?: number;
}> = ({ value, onValueChange, visibleCount = 0, totalCount = 0 }) => {
const styles = useStyles();
const { version } = runtime.getManifest();
const isPreserve = useListStore((state) => state.isPreserve);
const [settings, setSettings] = useSettings();
const { tagsToolbarVisible } = settings;
Expand Down Expand Up @@ -63,6 +69,7 @@ export const Footer: FC<{
{visibleCount} / {totalCount} requests
{isPreserve && ', log preserved'}
</span>
<div className={styles.version}>v.{version}</div>
<Link
text='Github'
href='https://github.com/Artboomy/netlogs'
Expand Down
5 changes: 0 additions & 5 deletions src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ const useStyles = createUseStyles({
alignItems: 'center',
gap: '8px'
},
version: {
fontStyle: 'italic'
},
optionsButton: {
// marginLeft: 'auto'
},
Expand Down Expand Up @@ -92,7 +89,6 @@ export const Header: FC<IProps> = ({
onCaseSensitiveChange
}) => {
const styles = useStyles();
const { version } = runtime.getManifest();
const clear = useListStore((state) => state.clear);
const isPreserve = useListStore((state) => state.isPreserve);
const [secondRowVisible, setSecondRowVisible] = useState(false);
Expand Down Expand Up @@ -173,7 +169,6 @@ export const Header: FC<IProps> = ({
onClick={doExport}
title='Export'
/>
<div className={styles.version}>v.{version}</div>
</div>
{secondRowVisible && (
<div className={styles.row}>
Expand Down
3 changes: 2 additions & 1 deletion src/components/IconButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,6 @@ export const ICONS: Record<string, IconButtonProps['icon']> = {
filter: '-56px 120px',
panelDown: '-116px 0px',
panelRight: '136px 168px',
panelUp: '136px -72px'
panelUp: '136px -72px',
inspect: '136px -72px'
} as const;
9 changes: 8 additions & 1 deletion src/components/PanelMain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { FilterContext } from '../context/FilterContext';
import { useHotkey } from '../hooks/useHotkey';
import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.min.css';
import { callParentVoid } from '../utils';
import { callParentVoid, subscribeParent } from '../utils';

const useStyles = createUseStyles({
'@global': {
Expand Down Expand Up @@ -79,6 +79,13 @@ export const PanelMain: React.FC = () => {
useEffect(() => {
callParentVoid('analytics.init');
}, []);

useEffect(() => {
subscribeParent('searchOnPage', (str) => {
setSearchValue(str);
callParentVoid('analytics.searchOnPage');
});
}, []);
return (
<DndProvider backend={HTML5Backend}>
<SettingsContainer>
Expand Down
29 changes: 29 additions & 0 deletions src/content/background.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
chrome.runtime.onInstalled.addListener(async () => {
chrome.contextMenus.create({
id: 'netlogs',
title: 'Search in Netlogs',
type: 'normal',
contexts: ['selection']
});
});
chrome.contextMenus.onClicked.addListener((item, tab) => {
const id = tab && tab.id;
if (id && ports[id]) {
ports[id].postMessage({
type: 'searchOnPage',
value: item.selectionText
});
}
});

const ports = {};

chrome.runtime.onConnect.addListener(function (port) {
if (port.name.startsWith('netlogs-')) {
const id = port.name.split('-')[1];
ports[id] = port;
port.onDisconnect.addListener(() => {
delete ports[id];
});
}
});
33 changes: 30 additions & 3 deletions src/sandboxUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,12 @@ export async function wrapSandbox(): Promise<void> {
entriesCount: Number(data)
});
break;
case 'analytics.error':
analyticsError(data);
break;
case 'analytics.searchOnPage':
analytics.fireEvent('searchOnPage');
break;
default:
console.warn(`Unrecognized type ${type}`);
}
Expand All @@ -156,6 +162,23 @@ export async function wrapSandbox(): Promise<void> {
});
}

const portToBackground = window.chrome.runtime.connect({
name: `netlogs-${window.chrome.devtools.inspectedWindow.tabId}`
});

portToBackground.onMessage.addListener((message) => {
if (message.type === 'searchOnPage') {
postSandbox(createEventPayload('searchOnPage', message.value));
}
});

function analyticsError(data: string) {
const { message, stack } = JSON.parse(data);
const error = new Error(message);
error.stack = stack;
analytics.fireErrorEvent(error);
}

async function analyticsInit() {
// determine if settings matcher is equal to default settings matcher
const settings = await chrome.storage.local
Expand All @@ -166,9 +189,13 @@ async function analyticsInit() {
const strSettings = settings.matcher.toString();
const strDefaultSettings = defaultSettings.matcher.toString();
// fire event with payload flag
analytics.fireEvent('matcherType', {
type: strSettings === strDefaultSettings ? 'default' : strSettings
});
if (strSettings === strDefaultSettings) {
analytics.fireEvent('matcherTypeDefault', {});
} else {
analytics.fireEvent('matcherTypeCustom', {
source: `"${strSettings}"`
});
}
}

function openTab(data: string) {
Expand Down
6 changes: 4 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type NetworkEventName =

type DevtoolsEventName = 'devtools.inspectedWindow.reload';

type CustomEventName = 'newItem' | 'download';
type CustomEventName = 'newItem' | 'download' | 'searchOnPage';

type TabEventName = 'chrome.tabs.create';

Expand All @@ -32,7 +32,9 @@ type AnalyticsEventName =
| 'analytics.mimeFilterChange'
| 'analytics.propTreeViewed'
| 'analytics.hotkey'
| 'analytics.fileOpen';
| 'analytics.fileOpen'
| 'analytics.error'
| 'analytics.searchOnPage';

export type EventName =
| 'onIframeReady'
Expand Down
Loading

0 comments on commit 01ad5f7

Please sign in to comment.