Hone logo
Hone
Problems

Implement a Logging Proxy in JavaScript

The Proxy pattern is a structural design pattern that provides a surrogate or placeholder for another object to control access to it. This challenge will focus on implementing a logging proxy that intercepts method calls to an underlying object and logs information about each call. This is useful for auditing, debugging, or adding cross-cutting concerns without modifying the original object.

Problem Description

Your task is to create a JavaScript LoggingProxy that wraps an existing object. This proxy should intercept all method calls made to the wrapped object. For each intercepted method call, the proxy must:

  1. Log the name of the method being called.
  2. Log any arguments passed to the method.
  3. Execute the original method on the wrapped object.
  4. Log the return value of the method.
  5. Return the original method's return value.

You should use JavaScript's built-in Proxy object for this implementation.

Key Requirements:

  • The proxy must handle any method that can be called on the target object.
  • The logging should clearly indicate the method name, its arguments, and its return value.
  • The original functionality of the target object must be preserved.

Expected Behavior:

When a method is called on the proxy, you should see log messages in the console detailing the operation. The proxy should behave exactly like the original object in terms of functionality.

Edge Cases to Consider:

  • Methods with no arguments.
  • Methods that return undefined.
  • Methods that throw errors (though for this challenge, we'll assume successful execution for logging purposes; error handling can be a future extension).

Examples

Example 1:

const calculator = {
  add: function(a, b) {
    return a + b;
  },
  subtract: function(a, b) {
    return a - b;
  }
};

const loggingCalculator = new LoggingProxy(calculator);

console.log(loggingCalculator.add(5, 3));
// Expected Console Output:
// Calling method: add
// Arguments: [5, 3]
// Returning: 8
// 8

console.log(loggingCalculator.subtract(10, 4));
// Expected Console Output:
// Calling method: subtract
// Arguments: [10, 4]
// Returning: 6
// 6

Explanation:

The LoggingProxy intercepts calls to add and subtract. It logs the method name and arguments, then executes the original method, logs the return value, and finally returns the result.

Example 2:

const greeter = {
  greet: function(name) {
    return `Hello, ${name}!`;
  },
  farewell: function() {
    return "Goodbye!";
  }
};

const loggingGreeter = new LoggingProxy(greeter);

console.log(loggingGreeter.greet("Alice"));
// Expected Console Output:
// Calling method: greet
// Arguments: ["Alice"]
// Returning: Hello, Alice!
// Hello, Alice!

console.log(loggingGreeter.farewell());
// Expected Console Output:
// Calling method: farewell
// Arguments: []
// Returning: Goodbye!
// Goodbye!

Explanation:

This example shows the proxy handling methods with and without arguments, demonstrating its flexibility.

Constraints

  • The proxy must be implemented using new Proxy(target, handler).
  • The handler object should use the get trap to intercept method calls.
  • All logging should be done using console.log().
  • The target object can have any number of methods.

Notes

  • Consider how to access and invoke the original methods on the target object within the get trap.
  • Remember that Proxy intercepts property access, not just method calls directly. You'll need to check if the accessed property is a function before attempting to call it.
  • The handler.get trap receives target, property, and receiver as arguments. The property argument will be the name of the method being accessed.
Loading editor...
javascript