diff --git a/lib/logger/index.spec.ts b/lib/logger/index.spec.ts
index c6de2300da9b2e6ca40d0c7f11a00c5158acffd8..d55c13a68b667c569f4519c13e7fda0ea0d7e5fa 100644
--- a/lib/logger/index.spec.ts
+++ b/lib/logger/index.spec.ts
@@ -152,6 +152,10 @@ describe('logger/index', () => {
     });
     add({ password: 'secret"password' });
 
+    class SomeClass {
+      constructor(public field: string) {}
+    }
+
     logger.error({
       foo: 'secret"password',
       bar: ['somethingelse', 'secret"password'],
@@ -162,6 +166,8 @@ describe('logger/index', () => {
       secrets: {
         foo: 'barsecret',
       },
+      someFn: () => 'secret"password',
+      someObject: new SomeClass('secret"password'),
     });
 
     expect(logged.foo).not.toBe('secret"password');
@@ -173,5 +179,7 @@ describe('logger/index', () => {
     expect(logged.content).toBe('[content]');
     expect(logged.prBody).toBe('[Template]');
     expect(logged.secrets.foo).toBe('***********');
+    expect(logged.someFn).toBe('[function]');
+    expect(logged.someObject.field).toBe('**redacted**');
   });
 });
diff --git a/lib/logger/utils.ts b/lib/logger/utils.ts
index b8d6ebef2c3391880396d1b8ce874969dc0f51ab..ab00f9746e5b4dda7f04d0f804202b065bf73ece 100644
--- a/lib/logger/utils.ts
+++ b/lib/logger/utils.ts
@@ -1,4 +1,5 @@
 import { Stream } from 'stream';
+import is from '@sindresorhus/is';
 import bunyan from 'bunyan';
 import fs from 'fs-extra';
 import { clone } from '../util/clone';
@@ -90,38 +91,54 @@ export default function prepareError(err: Error): Record<string, unknown> {
   return response;
 }
 
-export function sanitizeValue(_value: unknown, seen = new WeakMap()): any {
-  let value = _value;
-  if (Array.isArray(value)) {
-    const length = value.length;
-    const arrayResult = Array(length);
-    seen.set(value, arrayResult);
-    for (let idx = 0; idx < length; idx += 1) {
-      const val = value[idx];
-      arrayResult[idx] = seen.has(val)
-        ? seen.get(val)
-        : sanitizeValue(val, seen);
-    }
-    return arrayResult;
+type NestedValue = unknown[] | object;
+
+function isNested(value: unknown): value is NestedValue {
+  return is.array(value) || is.object(value);
+}
+
+export function sanitizeValue(
+  value: unknown,
+  seen = new WeakMap<NestedValue, unknown>()
+): any {
+  if (is.string(value)) {
+    return sanitize(value);
   }
 
-  if (value instanceof Buffer) {
-    return '[content]';
+  if (is.date(value)) {
+    return value;
   }
 
-  if (value instanceof Error) {
-    value = prepareError(value);
+  if (is.function_(value)) {
+    return '[function]';
   }
 
-  const valueType = typeof value;
+  if (is.buffer(value)) {
+    return '[content]';
+  }
+
+  if (is.error(value)) {
+    const err = prepareError(value);
+    return sanitizeValue(err, seen);
+  }
 
-  if (value && valueType !== 'function' && valueType === 'object') {
-    if (value instanceof Date) {
-      return value;
+  if (is.array(value)) {
+    const length = value.length;
+    const arrayResult = Array(length);
+    seen.set(value, arrayResult);
+    for (let idx = 0; idx < length; idx += 1) {
+      const val = value[idx];
+      arrayResult[idx] =
+        isNested(val) && seen.has(val)
+          ? seen.get(val)
+          : sanitizeValue(val, seen);
     }
+    return arrayResult;
+  }
 
+  if (is.object(value)) {
     const objectResult: Record<string, any> = {};
-    seen.set(value as any, objectResult);
+    seen.set(value, objectResult);
     for (const [key, val] of Object.entries<any>(value)) {
       let curValue: any;
       if (!val) {
@@ -143,10 +160,11 @@ export function sanitizeValue(_value: unknown, seen = new WeakMap()): any {
 
       objectResult[key] = curValue;
     }
+
     return objectResult;
   }
 
-  return valueType === 'string' ? sanitize(value as string) : value;
+  return value;
 }
 
 export function withSanitizer(streamConfig: bunyan.Stream): bunyan.Stream {