Last active
August 15, 2019 19:18
Star
You must be signed in to star a gist
JavaScript / ES6 sufficient to polyfill missing window.console (wholesale, or specific missing methods), identify local development vs. production, squelch certain logging operations in production, and rote console interactions (in non-file: protocol environments) to the back-end server for archival, analytics, etc.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict";!function(){const e=new RegExp("^"+["([^.].)+local","([^.].)+example","([^.].)+test","([^.].)+internal","([^.].)*localhost","127.0.0.1","::1"].join("|")+"$","i"),o="file:"==window.location.protocol||e.test(window.location.hostname),i=()=>{},n=(e,...o)=>{fetch(`/meta/collect/${e}`,{method:"POST",mode:"same-origin",cache:"no-cache",credentials:"same-origin",redirect:"error",referrer:"client",headers:{"Content-Type":"application/json"},body:JSON.stringify({args:o})})},t=["assert","clear","count","countReset","debug","dir","dirxml","error","exception","group","groupCollapsed","groupEnd","info","log","markTimeline","profile","profileEnd","table","time","timeEnd","timeLog","timeStamp","timeline","timelineEnd","trace","warn"],r=["debug","error","exception","info","log","table","trace","warn"],l=["debug","info","log"];var c=window.console=window.console||{},a={};for(let e of t)c[e]||(c[e]=i.bind(c));if(!o)for(let e of l)c[e]=i.bind(c);if("file:"!=window.location.protocol)for(let e of r)a[e]=c[e],l.includes(e)?c[e]=n.bind(c,e):c[e]=((...o)=>{n(e,...o),a[e](...o)})}(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://console.spec.whatwg.org | |
// https://github.com/whatwg/console | |
// http://nkashyap.github.io/console.io/ | |
// console.* Polyfill and, in production, no-op replacement. | |
(function() { | |
// An inspired polyfill for standard web browser user agent console interactions. | |
// | |
// This serves several purposes: | |
// | |
// 1. Add standardized methods missing from the local implementation to prevent code calling these from producing exceptions which halt JavaScript execution. | |
// 2. Direct certain logging actions at a back-end server collection endpoint, for archival, analytics, and diagnostics. | |
// 3. Squelch (mute or silence) "noisier" console endpoints to prevent user agents from exposing diagnostic information to end-users. | |
// Determine if we are running in "local development" or not based on hostname and protocol. | |
const LOCAL = new RegExp("^" + [ | |
"([^\.]\.)+local", // DNS-SD ("Bonjour") local-network automatic hostnames. | |
"([^\.]\.)+example", // Reserved for private use. | |
"([^\.]\.)+test", // Reserved for private use. | |
"([^\.]\.)+internal", // Reserved for private use. | |
"([^\.]\.)*localhost", // Loopback interface by name. | |
"127.0.0.1", // IPv4 loopback interface. | |
"::1", // IPv6 loopback interface. | |
].join("|") + "$", "i"); | |
const ISLOCAL = (window.location.protocol == 'file:') || LOCAL.test(window.location.hostname); | |
const NOOP = () => {}; | |
const COLLECT = (event, ...args) => { fetch(`/meta/collect/${event}`, { | |
method: 'POST', | |
mode: 'same-origin', | |
cache: 'no-cache', | |
credentials: 'same-origin', | |
redirect: 'error', | |
referrer: 'client', | |
headers: {'Content-Type': 'application/json'}, | |
body: JSON.stringify({'args': args}), | |
}) }; | |
const METHODS = [ | |
'assert', | |
'clear', | |
'count', | |
'countReset', | |
'debug', | |
'dir', | |
'dirxml', | |
'error', | |
'exception', // Deprecated! Do not use, prefer `error` instead! | |
'group', | |
'groupCollapsed', | |
'groupEnd', | |
'info', | |
'log', | |
'markTimeline', // Deprecated, WebKit-specific! Use timeStamp instead! | |
'profile', | |
'profileEnd', | |
'table', | |
'time', | |
'timeEnd', | |
'timeLog', | |
'timeStamp', // Deprecated, removed, and WebKit-specific! | |
'timeline', // Deprecated! | |
'timelineEnd', // Deprecated! | |
'trace', | |
'warn', | |
]; | |
const INSTRUMENT = [ | |
'debug', | |
'error', | |
'exception', | |
'info', | |
'log', | |
'table', | |
'trace', | |
'warn', | |
]; | |
const SILENCE = [ // In "production" silence these logging levels. | |
'debug', | |
'info', | |
'log', | |
] | |
var console = (window.console = window.console || {}); | |
var original = {}; // Needs to be exposed to nested contexts, thus not 'let'. | |
// Only populate ("polyfill") missing (undefined) methods. | |
for ( let method of METHODS ) | |
if ( !console[method] ) | |
console[method] = NOOP.bind(console); | |
// "Silence" certain logging levels/methods in production environments. | |
if ( !ISLOCAL ) | |
for ( let method of SILENCE ) | |
console[method] = NOOP.bind(console); | |
// Instrument (interpose) specific methods to route those classes of message to the back-end. | |
// Do not do so if we are served from the file: protocol, as there is no server to accept these notifications. | |
if ( window.location.protocol != 'file:' ) | |
for ( let method of INSTRUMENT ) { | |
original[method] = console[method]; | |
if ( SILENCE.includes(method) ) | |
console[method] = COLLECT.bind(console, method); | |
else | |
console[method] = (...args) => { COLLECT(method, ...args); original[method](...args) }; | |
} | |
}()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment