Skip to content

Instantly share code, notes, and snippets.

@burdiuz
Last active June 1, 2021 04:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save burdiuz/104ca430d05c0f5a0e8bfe66f936032f to your computer and use it in GitHub Desktop.
Save burdiuz/104ca430d05c0f5a0e8bfe66f936032f to your computer and use it in GitHub Desktop.
logAccessTo() returns proxy of an object that logs out access to its members

Replace original object with return value of logAccessTo and look into console for log messages.

window.test = logAccessTo({value1: 1, valueR: 'r', method: (arg) => arg + 1});
test.unknownGetter;
test.valueR;
test.valueR = 'Z';
test.valueR;
test.method(15);

Output:

07:12:22.156 <GET: unknownGetter = undefined
07:12:22.156 <GET: valueR = r
07:12:22.157 >SET: valueR = Z
07:12:22.157 <GET: valueR = Z
07:12:22.157 CALL: method ( 15 )
const interceptCallsTo = (() => {
const pad = (value) => String(value).padStart(2, '0');
const getTime = (date = new Date()) =>
`${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(
date.getSeconds(),
)}.${pad(date.getMilliseconds())}`;
return (obj, props = []) => {
const filtered = props && props.length;
Object.keys(obj).forEach((key) => {
const value = obj[key];
if (
!value ||
typeof value !== 'function' ||
(filtered && !props.includes(key))
) {
return;
}
if (value.__interceptor__) {
console.log(` - "${String(key)}" already set to be intercepted.`);
return;
}
const interceptor = (...args) => {
try {
console.log(getTime(), 'CALL:', name, '(', ...args, ')');
} catch (error) {
console.log(`Could not log "${String(key)}" method call`);
}
return value.apply(obj, args);
};
obj[key] = Object.assign(interceptor, { __interceptor__: true });
});
return obj;
};
})();
const interceptCallsToPropTarget = (base, name, props) => {
let obj;
Object.defineProperty(base, name, {
get: () => obj,
set: (value) => {
if (value) {
try {
console.log('Interception Target updated to:', value);
} catch (error) {
console.log(`Could not log interception target update for "${name}"`);
}
interceptCallsTo(value, props);
}
obj = value;
return true;
},
});
};
export const logAccessTo = (() => {
const pad = (value) => String(value).padStart(2, '0');
const getTime = (date = new Date()) => `${
pad(date.getHours())}:${
pad(date.getMinutes())}:${
pad(date.getSeconds())}.${
pad(date.getMilliseconds())}`;
return (obj, props = []) => {
const filtered = props && props.length;
return new Proxy(obj, {
get: (target, name, receiver) => {
const value = target[name];
if (!filtered || props.includes(name)) {
if (typeof value === 'function') {
return new Proxy(value, {
apply: (fn, thisArg, args) => {
try {
console.log(getTime(), 'CALL:', name, '(', ...args, ')');
if (receiver !== thisArg && target !== thisArg) {
console.log(' - applied to', thisArg);
}
} catch (error) {
console.log(`Could not log "${String(name)}" method call`);
}
return target[name](...args);
},
});
} else {
try {
console.log(getTime(), '<GET:', name, '=', value);
} catch (error) {
console.log(`Could not log accessing "${String(name)}"`);
}
}
}
return value;
},
set: (target, name, value) => {
if (!filtered || props.includes(name)) {
try {
console.log(getTime(), '>SET:', name, '=', value);
} catch (error) {
console.log(`Could not log setting "${String(name)}"`);
}
}
return (target[name] = value);
},
});
};
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment