diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md
index 0efc6ec42e15012e113507bd8a20f278e461ad91..a84fe56d306eb3cf728e2e7a1a1dbead303b2e0e 100644
--- a/docs/usage/configuration-options.md
+++ b/docs/usage/configuration-options.md
@@ -1796,6 +1796,21 @@ You can configure a different maximum value in seconds using `maxRetryAfter`:
 }
 ```
 
+### newLogLevel
+
+For log level remapping, `newLogLevel` will set for the particular log message:
+
+```json
+{
+  "logLevelRemap": [
+    {
+      "matchMessage": "/Error executing maven wrapper update command/",
+      "newLogLevel": "warn"
+    }
+  ]
+}
+```
+
 ### dnsCache
 
 Enable got [dnsCache](https://github.com/sindresorhus/got/blob/v11.5.2/readme.md#dnsCache) support.
@@ -2155,6 +2170,27 @@ To enable `lockFileMaintenance` add this to your configuration:
 To reduce "noise" in the repository, Renovate performs `lockFileMaintenance` `"before 4am on monday"`, i.e. to achieve once-per-week semantics.
 Depending on its running schedule, Renovate may run a few times within that time window - even possibly updating the lock file more than once - but it hopefully leaves enough time for tests to run and automerge to apply, if configured.
 
+## logLevelRemap
+
+This option allows you to remap log levels for specific messages.
+
+Be careful with remapping `warn` or `error` messages to lower log levels, as it may hide important information.
+
+```json
+{
+  "logLevelRemap": [
+    {
+      "matchMessage": "/^pip-compile:/",
+      "newLogLevel": "info"
+    },
+    {
+      "matchMessage": "Package lookup error",
+      "newLogLevel": "warn"
+    }
+  ]
+}
+```
+
 ## major
 
 Add to this object if you wish to define rules that apply only to major updates.
@@ -2588,6 +2624,26 @@ Use this field to restrict rules to a particular package manager. e.g.
 
 For the full list of available managers, see the [Supported Managers](modules/manager/index.md#supported-managers) documentation.
 
+### matchMessage
+
+For log level remapping, use this field to match against the particular log messages.
+You can match based on any of the following:
+
+- an exact match string (e.g. `This is the string`)
+- a minimatch pattern (e.g. `This*`)
+- a regex pattern (e.g. `/^This/`)
+
+```json
+{
+  "logLevelRemap": [
+    {
+      "matchMessage": "Manager explicitly enabled*",
+      "newLogLevel": "warn"
+    }
+  ]
+}
+```
+
 ### matchDatasources
 
 Use this field to restrict rules to a particular datasource. e.g.
diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts
index 214d2ec7ca335aeeded6453038b6b51573f4deb6..0c3203e4401f08cd607cfc924c977df6c3f2cd62 100644
--- a/lib/config/options/index.ts
+++ b/lib/config/options/index.ts
@@ -2818,6 +2818,32 @@ const options: RenovateOptions[] = [
     cli: false,
     env: false,
   },
+  {
+    name: 'logLevelRemap',
+    description: 'Remap log levels to different levels.',
+    type: 'array',
+    subType: 'object',
+    stage: 'repository',
+    cli: false,
+    env: false,
+  },
+  {
+    name: 'matchMessage',
+    description: 'Regex/minimatch expression to match against log message.',
+    type: 'string',
+    parents: ['logLevelRemap'],
+    cli: false,
+    env: false,
+  },
+  {
+    name: 'newLogLevel',
+    description: 'New log level to use if matchMessage matches.',
+    type: 'string',
+    allowedValues: ['trace', 'debug', 'info', 'warn', 'error', 'fatal'],
+    parents: ['logLevelRemap'],
+    cli: false,
+    env: false,
+  },
 ];
 
 export function getOptions(): RenovateOptions[] {
diff --git a/lib/config/types.ts b/lib/config/types.ts
index c18f8ace772fd44f252caee4f7673345120b84c9..dc9a690db41b7935fcaa070cac51b53e9035fefd 100644
--- a/lib/config/types.ts
+++ b/lib/config/types.ts
@@ -1,5 +1,6 @@
 import type { LogLevel } from 'bunyan';
 import type { PlatformId } from '../constants';
+import type { LogLevelRemap } from '../logger/types';
 import type { CustomManager } from '../modules/manager/custom/types';
 import type { HostRule } from '../types';
 import type { GitNoVerifyOption } from '../util/git/types';
@@ -275,6 +276,8 @@ export interface RenovateConfig
   customizeDashboard?: Record<string, string>;
 
   statusCheckNames?: Record<StatusCheckKey, string | null>;
+
+  logLevelRemap?: LogLevelRemap[];
 }
 
 const CustomDatasourceFormats = ['json', 'plain', 'yaml', 'html'] as const;
@@ -374,7 +377,8 @@ export type AllowedParents =
   | 'customDatasources'
   | 'hostRules'
   | 'postUpgradeTasks'
-  | 'packageRules';
+  | 'packageRules'
+  | 'logLevelRemap';
 export interface RenovateOptionBase {
   /**
    * If true, the option can only be configured by people with access to the Renovate instance.
diff --git a/lib/logger/index.ts b/lib/logger/index.ts
index 7e90ab4d841cea3b38f121ff5756cd8952e73055..54cb4ebf4e497adcecd8ff8df08abdafd86e6ad1 100644
--- a/lib/logger/index.ts
+++ b/lib/logger/index.ts
@@ -6,6 +6,7 @@ import configSerializer from './config-serializer';
 import errSerializer from './err-serializer';
 import { once, reset as onceReset } from './once';
 import { RenovateStream } from './pretty-stdout';
+import { getRemappedLevel } from './remap';
 import type { BunyanRecord, Logger } from './types';
 import { ProblemStream, validateLogLevel, withSanitizer } from './utils';
 
@@ -61,20 +62,39 @@ const bunyanLogger = bunyan.createLogger({
   ].map(withSanitizer),
 });
 
-const logFactory =
-  (level: bunyan.LogLevelString) =>
-  (p1: any, p2: any): void => {
+const logFactory = (
+  _level: bunyan.LogLevelString,
+): ((p1: unknown, p2: unknown) => void) => {
+  return (p1: any, p2: any): void => {
+    let level = _level;
     if (p2) {
       // meta and msg provided
-      bunyanLogger[level]({ logContext, ...curMeta, ...p1 }, p2);
+      const msg = p2;
+      const meta: Record<string, unknown> = { logContext, ...curMeta, ...p1 };
+      const remappedLevel = getRemappedLevel(msg);
+      // istanbul ignore if: not testable
+      if (remappedLevel) {
+        meta.oldLevel = level;
+        level = remappedLevel;
+      }
+      bunyanLogger[level](meta, msg);
     } else if (is.string(p1)) {
       // only message provided
-      bunyanLogger[level]({ logContext, ...curMeta }, p1);
+      const msg = p1;
+      const meta: Record<string, unknown> = { logContext, ...curMeta };
+      const remappedLevel = getRemappedLevel(msg);
+      // istanbul ignore if: not testable
+      if (remappedLevel) {
+        meta.oldLevel = level;
+        level = remappedLevel;
+      }
+      bunyanLogger[level](meta, msg);
     } else {
       // only meta provided
       bunyanLogger[level]({ logContext, ...curMeta, ...p1 });
     }
   };
+};
 
 const loggerLevels: bunyan.LogLevelString[] = [
   'trace',
diff --git a/lib/logger/remap.spec.ts b/lib/logger/remap.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3e7608971e27c748d1441f81458486d60499a057
--- /dev/null
+++ b/lib/logger/remap.spec.ts
@@ -0,0 +1,72 @@
+import {
+  getRemappedLevel,
+  resetGlobalLogLevelRemaps,
+  resetRepositoryLogLevelRemaps,
+  setGlobalLogLevelRemaps,
+  setRepositoryLogLevelRemaps,
+} from './remap';
+
+describe('logger/remap', () => {
+  afterEach(() => {
+    resetRepositoryLogLevelRemaps();
+    resetGlobalLogLevelRemaps();
+  });
+
+  it('returns null if no remaps are set', () => {
+    setGlobalLogLevelRemaps(undefined);
+    setRepositoryLogLevelRemaps(undefined);
+
+    const res = getRemappedLevel('foo');
+
+    expect(res).toBeNull();
+  });
+
+  it('performs global remaps', () => {
+    setGlobalLogLevelRemaps([{ matchMessage: '*foo*', newLogLevel: 'error' }]);
+    setRepositoryLogLevelRemaps(undefined);
+
+    const res = getRemappedLevel('foo');
+
+    expect(res).toBe('error');
+  });
+
+  it('performs repository-level remaps', () => {
+    setGlobalLogLevelRemaps(undefined);
+    setRepositoryLogLevelRemaps([
+      { matchMessage: '*bar*', newLogLevel: 'error' },
+    ]);
+
+    const res = getRemappedLevel('bar');
+
+    expect(res).toBe('error');
+  });
+
+  it('prioritizes repository-level remaps over global remaps', () => {
+    setGlobalLogLevelRemaps([{ matchMessage: '*foo*', newLogLevel: 'error' }]);
+    setRepositoryLogLevelRemaps([
+      { matchMessage: '*bar*', newLogLevel: 'warn' },
+    ]);
+
+    const res = getRemappedLevel('foobar');
+
+    expect(res).toBe('warn');
+  });
+
+  it('supports regex patterns', () => {
+    setGlobalLogLevelRemaps([{ matchMessage: '/foo/', newLogLevel: 'error' }]);
+    setRepositoryLogLevelRemaps(undefined);
+
+    const res = getRemappedLevel('foo');
+
+    expect(res).toBe('error');
+  });
+
+  it('does not match against invalid regex patterns', () => {
+    setGlobalLogLevelRemaps([{ matchMessage: '/(/', newLogLevel: 'error' }]);
+    setRepositoryLogLevelRemaps(undefined);
+
+    const res = getRemappedLevel('()');
+
+    expect(res).toBeNull();
+  });
+});
diff --git a/lib/logger/remap.ts b/lib/logger/remap.ts
new file mode 100644
index 0000000000000000000000000000000000000000..57920e2677ea003b6d57feaddf832466344b834c
--- /dev/null
+++ b/lib/logger/remap.ts
@@ -0,0 +1,68 @@
+import type { LogLevelString } from 'bunyan';
+import {
+  StringMatchPredicate,
+  makeRegexOrMinimatchPredicate,
+} from '../util/string-match';
+import type { LogLevelRemap } from './types';
+
+let globalRemaps: LogLevelRemap[] | undefined;
+let repositoryRemaps: LogLevelRemap[] | undefined;
+
+let matcherCache = new WeakMap<LogLevelRemap, StringMatchPredicate>();
+
+function match(remap: LogLevelRemap, input: string): boolean {
+  const { matchMessage: pattern } = remap;
+  let matchFn = matcherCache.get(remap);
+  if (!matchFn) {
+    matchFn = makeRegexOrMinimatchPredicate(pattern) ?? (() => false);
+    matcherCache.set(remap, matchFn);
+  }
+
+  return matchFn(input);
+}
+
+export function getRemappedLevel(msg: string): LogLevelString | null {
+  if (repositoryRemaps) {
+    for (const remap of repositoryRemaps) {
+      if (match(remap, msg)) {
+        return remap.newLogLevel;
+      }
+    }
+  }
+
+  if (globalRemaps) {
+    for (const remap of globalRemaps) {
+      if (match(remap, msg)) {
+        return remap.newLogLevel;
+      }
+    }
+  }
+
+  return null;
+}
+
+function resetMatcherCache(): void {
+  matcherCache = new WeakMap();
+}
+
+export function setGlobalLogLevelRemaps(
+  remaps: LogLevelRemap[] | undefined,
+): void {
+  globalRemaps = remaps;
+}
+
+export function resetGlobalLogLevelRemaps(): void {
+  globalRemaps = undefined;
+  resetMatcherCache();
+}
+
+export function setRepositoryLogLevelRemaps(
+  remaps: LogLevelRemap[] | undefined,
+): void {
+  repositoryRemaps = remaps;
+}
+
+export function resetRepositoryLogLevelRemaps(): void {
+  repositoryRemaps = undefined;
+  resetMatcherCache();
+}
diff --git a/lib/logger/types.ts b/lib/logger/types.ts
index 26fe16a73a814d67b8de56003eb3a5c9288c1b08..6880cc0f0c8901393a48d020c5f3752c6b12117d 100644
--- a/lib/logger/types.ts
+++ b/lib/logger/types.ts
@@ -1,5 +1,5 @@
 import type { Stream } from 'node:stream';
-import type { LogLevel } from 'bunyan';
+import type { LogLevel, LogLevelString } from 'bunyan';
 
 export interface LogError {
   level: LogLevel;
@@ -40,3 +40,8 @@ export type BunyanStream = (NodeJS.WritableStream | Stream) & {
     cb: (err?: Error | null) => void,
   ) => void;
 };
+
+export interface LogLevelRemap {
+  matchMessage: string;
+  newLogLevel: LogLevelString;
+}
diff --git a/lib/workers/global/index.ts b/lib/workers/global/index.ts
index e2c2a83a2358af8e07e7197e030b348b42882b8c..cd285c06ee769354fda60d98fa5d1584bcc9ac4e 100644
--- a/lib/workers/global/index.ts
+++ b/lib/workers/global/index.ts
@@ -17,6 +17,7 @@ import { CONFIG_PRESETS_INVALID } from '../../constants/error-messages';
 import { pkg } from '../../expose.cjs';
 import { instrument } from '../../instrumentation';
 import { getProblems, logger, setMeta } from '../../logger';
+import { setGlobalLogLevelRemaps } from '../../logger/remap';
 import * as hostRules from '../../util/host-rules';
 import * as queue from '../../util/http/queue';
 import * as throttle from '../../util/http/throttle';
@@ -158,6 +159,8 @@ export async function start(): Promise<number> {
 
       // validate secrets. Will throw and abort if invalid
       validateConfigSecrets(config);
+
+      setGlobalLogLevelRemaps(config.logLevelRemap);
     });
 
     // autodiscover repositories (needs to come after platform initialization)
diff --git a/lib/workers/global/initialize.ts b/lib/workers/global/initialize.ts
index 41af7f9a5af9d7136f6dc1124a2473973d742abe..47c780b4ea4049e22ebb5e1b933a3b698be1be82 100644
--- a/lib/workers/global/initialize.ts
+++ b/lib/workers/global/initialize.ts
@@ -4,6 +4,7 @@ import upath from 'upath';
 import { applySecretsToConfig } from '../../config/secrets';
 import type { AllConfig, RenovateConfig } from '../../config/types';
 import { logger } from '../../logger';
+import { resetGlobalLogLevelRemaps } from '../../logger/remap';
 import { initPlatform } from '../../modules/platform';
 import * as packageCache from '../../util/cache/package';
 import { setEmojiConfig } from '../../util/emoji';
@@ -93,4 +94,5 @@ export async function globalInitialize(
 
 export async function globalFinalize(config: RenovateConfig): Promise<void> {
   await packageCache.cleanup(config);
+  resetGlobalLogLevelRemaps();
 }
diff --git a/lib/workers/repository/index.ts b/lib/workers/repository/index.ts
index 6e775996ce0b55d1febb90fbbf2b938b36002a79..fa2294a0203b5dfd9091fcce6e1c12774c90652a 100644
--- a/lib/workers/repository/index.ts
+++ b/lib/workers/repository/index.ts
@@ -10,6 +10,7 @@ import {
 import { pkg } from '../../expose.cjs';
 import { instrument } from '../../instrumentation';
 import { logger, setMeta } from '../../logger';
+import { resetRepositoryLogLevelRemaps } from '../../logger/remap';
 import { removeDanglingContainers } from '../../util/exec/docker';
 import { deleteLocalFile, privateCacheDir } from '../../util/fs';
 import { isCloned } from '../../util/git';
@@ -129,6 +130,7 @@ export async function renovateRepository(
   clearDnsCache();
   const cloned = isCloned();
   logger.info({ cloned, durationMs: splits.total }, 'Repository finished');
+  resetRepositoryLogLevelRemaps();
   return repoResult;
 }
 
diff --git a/lib/workers/repository/init/index.ts b/lib/workers/repository/init/index.ts
index 374b1ec8c81a31ad8359f67735bc1ec29828020a..81f05826c03f10bba1bacc9caf0f752d87a9f196 100644
--- a/lib/workers/repository/init/index.ts
+++ b/lib/workers/repository/init/index.ts
@@ -2,6 +2,7 @@ import { GlobalConfig } from '../../../config/global';
 import { applySecretsToConfig } from '../../../config/secrets';
 import type { RenovateConfig } from '../../../config/types';
 import { logger } from '../../../logger';
+import { setRepositoryLogLevelRemaps } from '../../../logger/remap';
 import { platform } from '../../../modules/platform';
 import { clone } from '../../../util/clone';
 import { cloneSubmodules, setUserRepoConfig } from '../../../util/git';
@@ -50,6 +51,7 @@ export async function initRepo(
   config = await initApis(config);
   await initializeCaches(config as WorkerPlatformConfig);
   config = await getRepoConfig(config);
+  setRepositoryLogLevelRemaps(config.logLevelRemap);
   checkIfConfigured(config);
   warnOnUnsupportedOptions(config);
   config = applySecretsToConfig(config);