惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

MyScale Blog
MyScale Blog
L
LINUX DO - 最新话题
云风的 BLOG
云风的 BLOG
Know Your Adversary
Know Your Adversary
小众软件
小众软件
C
CERT Recently Published Vulnerability Notes
V
V2EX
The Hacker News
The Hacker News
P
Palo Alto Networks Blog
D
DataBreaches.Net
C
Cyber Attacks, Cyber Crime and Cyber Security
Microsoft Azure Blog
Microsoft Azure Blog
GbyAI
GbyAI
AWS News Blog
AWS News Blog
Forbes - Security
Forbes - Security
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
J
Java Code Geeks
美团技术团队
C
Cybersecurity and Infrastructure Security Agency CISA
Project Zero
Project Zero
Recorded Future
Recorded Future
宝玉的分享
宝玉的分享
Hacker News - Newest:
Hacker News - Newest: "LLM"
L
LINUX DO - 热门话题
W
WeLiveSecurity
V
Visual Studio Blog
Schneier on Security
Schneier on Security
有赞技术团队
有赞技术团队
P
Proofpoint News Feed
aimingoo的专栏
aimingoo的专栏
V2EX - 技术
V2EX - 技术
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Microsoft Security Blog
Microsoft Security Blog
U
Unit 42
N
Netflix TechBlog - Medium
F
Fortinet All Blogs
博客园_首页
I
InfoQ
Spread Privacy
Spread Privacy
博客园 - 叶小钗
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
L
LangChain Blog
月光博客
月光博客
I
Intezer
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
A
Arctic Wolf
S
SegmentFault 最新的问题
www.infosecurity-magazine.com
www.infosecurity-magazine.com
T
The Exploit Database - CXSecurity.com
Google DeepMind News
Google DeepMind News

Pierce Freeman

A browser for agents | Pierce Freeman The grey market of podcast appearances The way I travel | Pierce Freeman Fixing slow AWS uploads | Pierce Freeman Local tools should still use vaults We solved scratch content first Starting a podcast in 2025 Being late but still being early Automating our home video imports Adding my parents to tailscale A deep dive on agent sandboxes Language servers for AI | Pierce Freeman My simple home podcast studio We need centralized infrastructure | Pierce Freeman Coercing agents to follow conventions using AST validation My unified theory of social selling My personal backup strategy | Pierce Freeman July updates to the homelab How the KV Cache works httpx is the right way to do web requests in Python Reputation is becoming everything | Pierce Freeman Building a (kind of) invisible mac app Updated knowledge in language models Making an ascii animation | Pierce Freeman How speculative decoding works | Pierce Freeman Under the hood of Claude Code Doing things because they're easy, not hard Speeding up sideeffects with JIT in mountaineer Firehot for hot reloading in Python Misadventures in Python hot reloading How text diffusion works | Pierce Freeman The tenacity of modern LLMs The ergonomics of rails | Pierce Freeman How language servers work | Pierce Freeman Just add eggs | Pierce Freeman Unfortunately SEO still matters | Pierce Freeman The futility of human-only web requirements Setting up Input Leap | Pierce Freeman Checking in on Waymo | Pierce Freeman The react revolution | Pierce Freeman Speeding up many small transfers to a unifi nas Quick notes on swift libraries AI engineering is a different animal San Francisco | Pierce Freeman Debugging a mountaineer rendering segfault Local network config on macOS Building our home network | Pierce Freeman Introducing Envelope.dev | Pierce Freeman Legacy code and AI copilots Typehinting from day-zero | Pierce Freeman Generating database migrations with acyclic graphs Lofoten | Pierce Freeman Mountaineer v0.1: Webapps in Python and React Constraining LLM Outputs | Pierce Freeman Passthrough above all | Pierce Freeman Accuracy in kudos | Pierce Freeman How quick we are to adapt The curious case of LM repetition Costa Rica | Pierce Freeman Speeding up runpod | Pierce Freeman Inline footnotes with html templates Parsing Common Crawl in a day for $60 An era of rich CLI All or nothing with remote work The Next 10 Years | Pierce Freeman Adding wheels to flash-attention | Pierce Freeman LLMs as interdisciplinary agents | Pierce Freeman New Zealand | Pierce Freeman Representations in autoregressive models | Pierce Freeman Let's talk about Siri | Pierce Freeman Minimum viable public infrastructure | Pierce Freeman Reasoning vs. Memorization in LLMs Automatically migrate enums in alembic Greater sequence lengths will set us free On learning to ski | Pierce Freeman Dolomites | Pierce Freeman Using grpc with node and typescript Opportunity years | Pierce Freeman Buzzword peaks and valleys | Pierce Freeman Buenos Aires | Pierce Freeman Network routing interaction on MacOS Independent work: November recap | Pierce Freeman Debugging slow pytorch training performance The provenance of copy and paste Debugging tips for neural network training Patagonia | Pierce Freeman Santiago | Pierce Freeman My 2022 digital travel kit AWS vs GCP - GPU Availability V2 Independent work: October recap | Pierce Freeman Planning Patagonia | Pierce Freeman Relationship modeling | Pierce Freeman The power of status updates A new chapter | Pierce Freeman Give my library a coffee shop AWS vs GCP - GPU Availability V1 Switzerland | Pierce Freeman Headfull browsers beat headless | Pierce Freeman Webcrawling tradeoffs | Pierce Freeman Copenhagen | Pierce Freeman
Debugging chrome extensions with system-level logging
2023-12-19 · via Pierce Freeman

I've been working on a Chrome extension lately that's getting closer to a public release. That shifts my workflow from blue sky design to the basement - fighting every last bug.

Extensions are basically mini web applications these days, just with access to a chrome global variable that can interact with some browser-level functionality. Aside from that - it's all familiar. That extends to the debugging experience. Since extensions run in the regular V8 Chrome runtime, Chrome exposes the same debugging tools that you're used to on the web: profiling, stack tracing, code mapping, etc.

Unlike a regular website, however, the potential edge cases of an extension are practically infinite. They need to tolerate the whole universe of pages where you're applying them. I've found one of the best ways to catch these edge cases and diagnose them after the fact is to capture verbose logging to disk. You can browse the web as you test your extension and then review the workflow session logs afterward. The Inspector console of the background process is fleeting and often crashes if your logging volume is too high.

Enabling Verbosity

Per the Chromium docs, you can add verbosity on application startup. This logic works on Chrome as well:

/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --enable-logging --v=1

This logging file will be accessible during your run and after. It gets cleared the next time you launch Chrome with this logging command, however, so make sure to copy over what you need to a new file. You can inspect it (or pipe it) in realtime by running tail:

tail -f ~/Library/Application\ Support/Google/Chrome/chrome_debug.log

This should produce extension logs whether you're actively inspecting your service worker or just have it running in the background. From there you can open it in a log utility, duckdb, or just a simple grep.

grep "extension-error" ./chrome_debug.log

Logging Utility

This strategy is most useful if you log aggressively. If your logs aren't precise enough to pin down the bug, this approach loses much of the merit. I suggest a tunable logging class where your development builds will log every page URL, primary function call, expected value, etc. Your build pipeline can then clear these out before production.

Internally, we have a logging class a lot like this. It extends the default javascript console with a bit of syntax sugar to let flags determine whether messages actually make it to the console or are dropped.

The process.env variable default can be set by your build pipeline so you increase verbosity during development and scale it back for production. es-build makes this pretty easy.

export enum LOG_LEVELS {
    NONE = 0,
    ERROR = 1,
    WARN = 2,
    INFO = 3,
    DEBUG = 4,
}

const logToLevel = {
    NONE: LOG_LEVELS.NONE,
    ERROR: LOG_LEVELS.ERROR,
    WARN: LOG_LEVELS.WARN,
    INFO: LOG_LEVELS.INFO,
    DEBUG: LOG_LEVELS.DEBUG,
};

interface CustomConsole extends Console {
    logLevel?: string;
}

class CustomLogger {
    systemLogLevel: LOG_LEVELS;

    constructor() {
        const envDefault = process.env.PUBLIC_ENV_LOG_LEVEL! || 'INFO';
        let enumValue = logToLevel[envDefault as keyof typeof LOG_LEVELS];
        if (enumValue === undefined) {
            console.log(`Invalid log level ${envDefault}, defaulting to INFO`);
            enumValue = LOG_LEVELS.INFO;
        }

        this.systemLogLevel = enumValue;
    }

    setLogLevel(level: LOG_LEVELS) {
        this.systemLogLevel = level;
    }

    error(...args: any[]) {
        if (this.systemLogLevel >= LOG_LEVELS.ERROR) {
            console.error(...args);
        }
    }

    warn(...args: any[]) {
        if (this.systemLogLevel >= LOG_LEVELS.WARN) {
            console.warn(...args);
        }
    }

    info(...args: any[]) {
        if (this.systemLogLevel >= LOG_LEVELS.INFO) {
            console.info(...args);
        }
    }

    debug(...args: any[]) {
        if (this.systemLogLevel >= LOG_LEVELS.DEBUG) {
            console.log(...args);
        }
    }
}
export const defaultLogger = new CustomLogger();

Additional Notes

  • Make sure to format any important console.log values as JSON strings instead of the raw objects themselves. When Chrome saves the logs to disk it will format everything as strings which means that your rich objects will be serialized to [object Object], which doesn't make for the easiest debugging.
  • A heavy day of Chrome use will result in a log file of around 2GB. Maybe more maybe less depending on your logging verbosity. I periodically copy this over to another scratch location on disk so I don't lose any intermediate logs, but I haven't had an issue with data loss yet from the core logging file.