unfreezeInheritance method

void unfreezeInheritance({
  1. Set<String>? fields,
  2. bool includeSelf = true,
})

Unfreezes configurations that were previously frozen on descendant loggers.

Reverts fields populated by freezeInheritance back to null, restoring Unfreezes configurations that were previously frozen on descendant loggers.

Reverts fields populated by freezeInheritance back to null, restoring dynamic resolution from ancestor loggers. Fields that were explicitly configured by the user are not affected.

Parameters:

  • fields: Optional set of field names to selectively unfreeze. When provided, only those named fields are cleared — all other frozen fields are left intact. Unknown field names are silently ignored. When null (default), all frozen fields are cleared.
  • includeSelf: Whether to also unfreeze the receiver's own frozen fields. Defaults to true. Pass false to restrict the operation to strict descendants only.

Example: // Full subtree unfreeze (default) logger.unfreezeInheritance(); // Unfreeze only logLevel, excluding self logger.unfreezeInheritance(fields: {'logLevel'}, includeSelf: false);

Implementation

void unfreezeInheritance({
  final Set<String>? fields,
  final bool includeSelf = true,
}) {
  for (final key in _registry.keys.toList()) {
    final isSelf = key == name;
    if ((isSelf && !includeSelf) || (!isSelf && !_isDescendant(key, name))) {
      continue;
    }
    final childConfig = _registry[key]!;
    bool changed = false;
    if (childConfig.frozenFields.isNotEmpty) {
      // Determine which frozen fields to actually clear.
      final toClear = fields == null
          ? Set.of(childConfig.frozenFields)
          : childConfig.frozenFields.intersection(fields);

      final nextFrozenFields = Set<String>.from(childConfig.frozenFields);
      bool? newEnabled = childConfig.enabled;
      LogLevel? newLogLevel = childConfig.logLevel;
      bool? newIncludeFileLineInHeader = childConfig.includeFileLineInHeader;
      bool? newIncludeOrigin = childConfig.includeOrigin;
      Map<LogLevel, int>? newStackMethodCount = childConfig.stackMethodCount;
      Timestamp? newTimestamp = childConfig.timestamp;
      StackTraceParser? newStackTraceParser = childConfig.stackTraceParser;
      List<Handler>? newHandlers = childConfig.handlers;
      bool? newAutoSinkBuffer = childConfig.autoSinkBuffer;

      for (final field in toClear) {
        switch (field) {
          case 'enabled':
            newEnabled = null;
          case 'logLevel':
            newLogLevel = null;
          case 'includeFileLineInHeader':
            newIncludeFileLineInHeader = null;
          case 'includeOrigin':
            newIncludeOrigin = null;
          case 'stackMethodCount':
            newStackMethodCount = null;
          case 'timestamp':
            newTimestamp = null;
          case 'stackTraceParser':
            newStackTraceParser = null;
          case 'handlers':
            newHandlers = null;
          case 'autoSinkBuffer':
            newAutoSinkBuffer = null;
        }
        nextFrozenFields.remove(field);
        changed = true;
      }

      if (changed) {
        _registry[key] = childConfig.copyWith(
          enabled: newEnabled,
          logLevel: newLogLevel,
          includeFileLineInHeader: newIncludeFileLineInHeader,
          includeOrigin: newIncludeOrigin,
          stackMethodCount: newStackMethodCount,
          timestamp: newTimestamp,
          stackTraceParser: newStackTraceParser,
          handlers: newHandlers,
          autoSinkBuffer: newAutoSinkBuffer,
          version: childConfig.version + 1,
          frozenFields: nextFrozenFields,
        );
        LoggerCache.invalidate(key);
      }
    }
  }
}