Class: AbstractTokenProvider

Inherits:
Object
  • Object
show all
Defined in:
lib/fluent/plugin/auth/tokenprovider_base.rb

Overview

AbstractTokenProvider defines the interface and shared logic for all token providers. Enhanced with retry logic and better token expiry management to prevent timeout issues.

Instance Method Summary collapse

Constructor Details

#initialize(outconfiguration) ⇒ AbstractTokenProvider

Returns a new instance of AbstractTokenProvider.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/fluent/plugin/auth/tokenprovider_base.rb', line 9

def initialize(outconfiguration)
  @logger = setup_logger(outconfiguration)
  setup_config(outconfiguration)
  @token_state = { 
    access_token: nil, 
    expiry_time: nil, 
    token_details_mutex: Mutex.new,
    refresh_in_progress: false,
    consecutive_failures: 0,
    last_failure_time: nil,
    creation_time: Time.now,
    refresh_count: 0,
    last_successful_refresh: nil
  }
  
  # Simplified retry configuration using constants
  @retry_config = {
    max_retries: KustoConstants::Authentication::DEFAULT_MAX_RETRIES,
    base_delay: KustoConstants::Authentication::DEFAULT_BASE_DELAY,
    backoff_multiplier: KustoConstants::Authentication::DEFAULT_BACKOFF_MULTIPLIER,
    max_delay: KustoConstants::Authentication::DEFAULT_MAX_DELAY
  }
  
  # Minimal health configuration for 12-hour reset
  @health_config = {
    max_token_age: KustoConstants::HealthCheck::MAX_COMPONENT_AGE_SECONDS,
    max_refresh_cycles: KustoConstants::HealthCheck::MAX_REFRESH_CYCLES
  }
  
  # HTTP timeout configuration - consistent across all token providers
  @http_config = {
    open_timeout: KustoConstants::Authentication::HTTP_OPEN_TIMEOUT,
    read_timeout: KustoConstants::Authentication::HTTP_READ_TIMEOUT,
    write_timeout: KustoConstants::Authentication::HTTP_WRITE_TIMEOUT
  }
end

Instance Method Details

#fetch_tokenObject

Abstract method: must be implemented by subclasses to fetch a new token.

Raises:

  • (NotImplementedError)


47
48
49
# File 'lib/fluent/plugin/auth/tokenprovider_base.rb', line 47

def fetch_token
  raise NotImplementedError, 'Subclasses must implement fetch_token'
end

#get_health_statusObject

Thread-safe wrapper for health_status when called externally



86
87
88
89
90
# File 'lib/fluent/plugin/auth/tokenprovider_base.rb', line 86

def get_health_status
  @token_state[:token_details_mutex].synchronize do
    health_status
  end
end

#get_tokenObject

Public method to get a valid token, refreshing if needed with enhanced retry logic.



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/fluent/plugin/auth/tokenprovider_base.rb', line 52

def get_token
  @token_state[:token_details_mutex].synchronize do
    if saved_token_need_refresh?
      if @token_state[:refresh_in_progress]
        @logger.debug("Token refresh already in progress, waiting...")
        return wait_for_refresh_completion
      end
      
      @logger.info("Refreshing token. Previous expiry: #{@token_state[:expiry_time]}")
      refresh_saved_token_with_retry
      @logger.info("New token expiry: #{@token_state[:expiry_time]}")
    else
      @logger.debug("Reusing existing token (expires at #{@token_state[:expiry_time]})")
    end
    @token_state[:access_token]
  end
end

#health_statusObject

Health check method - returns health status as hash Note: This method should be called from within a synchronized context



72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/fluent/plugin/auth/tokenprovider_base.rb', line 72

def health_status
  {
    token_valid: !saved_token_need_refresh?,
    token_expires_at: @token_state[:expiry_time],
    consecutive_failures: @token_state[:consecutive_failures],
    last_failure_time: @token_state[:last_failure_time],
    refresh_in_progress: @token_state[:refresh_in_progress],
    refresh_count: @token_state[:refresh_count],
    last_successful_refresh: @token_state[:last_successful_refresh],
    token_age_hours: @token_state[:creation_time] ? (Time.now - @token_state[:creation_time]) / 3600 : 0
  }
end

#log_health_status(context = "") ⇒ Object

Log health status for operational visibility



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/fluent/plugin/auth/tokenprovider_base.rb', line 93

def log_health_status(context = "")
  status = health_status
  context_prefix = context.empty? ? "" : "#{context}: "
  
  @logger.info("#{context_prefix}Token provider health - " \
              "valid: #{status[:token_valid]}, " \
              "expires_at: #{status[:token_expires_at]}, " \
              "failures: #{status[:consecutive_failures]}, " \
              "refresh_count: #{status[:refresh_count]}, " \
              "age_hours: #{status[:token_age_hours].round(1)}")
  
  if status[:consecutive_failures] > 0
    @logger.warn("#{context_prefix}Token provider has #{status[:consecutive_failures]} consecutive failures, " \
                "last failure: #{status[:last_failure_time]}")
  end
end