tina4ruby 3.13.2 → 3.13.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/tina4/env.rb +60 -0
- data/lib/tina4/log.rb +39 -1
- data/lib/tina4/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6806b64505d23caba2d53a7b08b1411aa1e0ca924ea883d660dedae1c81f5766
|
|
4
|
+
data.tar.gz: e168b0a72f99e8cab66c1532a0909d480e10e330c65104749ec8dafb4e26837d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fd1d7d614b01886cb2e70ffcd04503ce3155073350f70dc92e6414816c5993a39b63b91965f49c30ea3275a6c72b62eea510ba64db74db0384ad925d7bdb0b76
|
|
7
|
+
data.tar.gz: 745992728883c28e11d3716977a9bb9e5f58d4a043b7aa285c6dc8113b8c95d3ffef10ac7b52aa339ef0172c308687f6c3004926af1daf1f4a3737601c008994
|
data/lib/tina4/env.rb
CHANGED
|
@@ -83,6 +83,14 @@ module Tina4
|
|
|
83
83
|
"TINA4_SECRET" => "tina4-secret-change-me"
|
|
84
84
|
}.freeze
|
|
85
85
|
|
|
86
|
+
# Typed env-var coercion — parity with tina4_python's Env class,
|
|
87
|
+
# tina4-php's Tina4\Env, and tina4-nodejs's Env. Truthy values
|
|
88
|
+
# (case-insensitive after strip): "1", "true", "on", "yes", "y", "t".
|
|
89
|
+
# Falsy: "0", "false", "off", "no", "n", "f", empty string. Anything
|
|
90
|
+
# else falls through to default.
|
|
91
|
+
TRUTHY = %w[1 true on yes y t].freeze
|
|
92
|
+
FALSY = %w[0 false off no n f].freeze
|
|
93
|
+
|
|
86
94
|
# Check if a value is truthy for env boolean checks.
|
|
87
95
|
#
|
|
88
96
|
# Accepts: "true", "True", "TRUE", "1", "yes", "Yes", "YES", "on", "On", "ON".
|
|
@@ -91,6 +99,58 @@ module Tina4
|
|
|
91
99
|
%w[true 1 yes on].include?(val.to_s.strip.downcase)
|
|
92
100
|
end
|
|
93
101
|
|
|
102
|
+
# Read an env var and coerce to Boolean. Returns +default+ when the
|
|
103
|
+
# var is unset or holds a value outside the TRUTHY/FALSY tables.
|
|
104
|
+
# Never raises — bad input falls through to default.
|
|
105
|
+
def self.bool(name, default: false)
|
|
106
|
+
raw = ENV[name.to_s]
|
|
107
|
+
return default if raw.nil?
|
|
108
|
+
token = raw.strip.downcase
|
|
109
|
+
return true if TRUTHY.include?(token)
|
|
110
|
+
return false if FALSY.include?(token) || token.empty?
|
|
111
|
+
default
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Read an env var and coerce to Integer. Logs a warning via Tina4::Log
|
|
115
|
+
# (if loaded) and returns +default+ on parse failure. Never raises.
|
|
116
|
+
def self.int(name, default: 0)
|
|
117
|
+
raw = ENV[name.to_s]
|
|
118
|
+
return default if raw.nil?
|
|
119
|
+
Integer(raw.strip)
|
|
120
|
+
rescue ArgumentError, TypeError
|
|
121
|
+
log_warning("Env.int(#{name.inspect}): could not parse #{raw.inspect} as Integer — using default #{default.inspect}")
|
|
122
|
+
default
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Read an env var and coerce to Float. Logs a warning via Tina4::Log
|
|
126
|
+
# (if loaded) and returns +default+ on parse failure. Never raises.
|
|
127
|
+
def self.float(name, default: 0.0)
|
|
128
|
+
raw = ENV[name.to_s]
|
|
129
|
+
return default if raw.nil?
|
|
130
|
+
Float(raw.strip)
|
|
131
|
+
rescue ArgumentError, TypeError
|
|
132
|
+
log_warning("Env.float(#{name.inspect}): could not parse #{raw.inspect} as Float — using default #{default.inspect}")
|
|
133
|
+
default
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Read an env var as a String. Returns +default+ when unset.
|
|
137
|
+
# Whitespace is preserved — this is a pass-through for the raw env value,
|
|
138
|
+
# matching Python's Env.str semantics.
|
|
139
|
+
def self.str(name, default: "")
|
|
140
|
+
raw = ENV[name.to_s]
|
|
141
|
+
return default if raw.nil?
|
|
142
|
+
raw
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Emit a warning via Tina4::Log without creating a load-order dependency.
|
|
146
|
+
# Mirrors Python's Env._log_warning: silently skip if Log isn't loaded.
|
|
147
|
+
def self.log_warning(message)
|
|
148
|
+
Tina4::Log.warning(message) if defined?(Tina4::Log)
|
|
149
|
+
rescue NameError, StandardError
|
|
150
|
+
# Log not wired up yet (very early bootstrap) — swallow.
|
|
151
|
+
end
|
|
152
|
+
private_class_method :log_warning
|
|
153
|
+
|
|
94
154
|
class << self
|
|
95
155
|
def load_env(root_dir = Dir.pwd)
|
|
96
156
|
env_file = resolve_env_file(root_dir)
|
data/lib/tina4/log.rb
CHANGED
|
@@ -203,8 +203,10 @@ module Tina4
|
|
|
203
203
|
ts = utc_timestamp
|
|
204
204
|
rid = get_request_id
|
|
205
205
|
rid_str = rid ? " [#{rid}]" : ""
|
|
206
|
+
fn = caller_name
|
|
207
|
+
fn_str = fn ? " [#{fn}]" : ""
|
|
206
208
|
ctx = @current_context && !@current_context.empty? ? " #{JSON.generate(@current_context)}" : ""
|
|
207
|
-
"#{ts} [#{level_str.ljust(7)}]#{rid_str} #{message}#{ctx}"
|
|
209
|
+
"#{ts} [#{level_str.ljust(7)}]#{rid_str}#{fn_str} #{message}#{ctx}"
|
|
208
210
|
end
|
|
209
211
|
|
|
210
212
|
def json_line(level, message)
|
|
@@ -216,10 +218,46 @@ module Tina4
|
|
|
216
218
|
}
|
|
217
219
|
rid = get_request_id
|
|
218
220
|
entry[:request_id] = rid if rid
|
|
221
|
+
fn = caller_name
|
|
222
|
+
entry[:function] = fn if fn
|
|
219
223
|
entry[:context] = @current_context if @current_context && !@current_context.empty?
|
|
220
224
|
JSON.generate(entry)
|
|
221
225
|
end
|
|
222
226
|
|
|
227
|
+
# Names that belong to Log itself — walk past them so the reported
|
|
228
|
+
# frame is the real caller (e.g. the route handler or service
|
|
229
|
+
# method that called Log.info). Kept as a Set for O(1) lookup.
|
|
230
|
+
OWN_FRAMES = %w[
|
|
231
|
+
caller_name format_line json_line log colorize write_to_file
|
|
232
|
+
debug info warning error critical
|
|
233
|
+
].freeze
|
|
234
|
+
|
|
235
|
+
# Names that are noise — Ruby block labels, lambdas, top-level
|
|
236
|
+
# script frames. We skip these the same way Python skips <module>
|
|
237
|
+
# and <lambda>.
|
|
238
|
+
NOISE_FRAME_RE = /\A(?:block(?: \(\d+ levels\))? in |<top \(required\)>|<main>)/
|
|
239
|
+
|
|
240
|
+
# Return the name of the function that called Log.{debug,info,warning,error}.
|
|
241
|
+
# Active only when TINA4_LOG_FUNC=true (parity feature #41).
|
|
242
|
+
# Returns nil on any error so it never crashes a log call.
|
|
243
|
+
def caller_name
|
|
244
|
+
return nil unless Tina4::Env.bool("TINA4_LOG_FUNC")
|
|
245
|
+
|
|
246
|
+
# caller_locations(2, 16) skips this method + log() and gives us
|
|
247
|
+
# up to 16 frames to walk. We bail out the moment we hit a frame
|
|
248
|
+
# whose base_label isn't in OWN_FRAMES and isn't a block label.
|
|
249
|
+
locs = caller_locations(2, 16) || []
|
|
250
|
+
locs.each do |loc|
|
|
251
|
+
label = loc.base_label.to_s
|
|
252
|
+
next if OWN_FRAMES.include?(label)
|
|
253
|
+
next if label.empty? || NOISE_FRAME_RE.match?(label)
|
|
254
|
+
return label
|
|
255
|
+
end
|
|
256
|
+
nil
|
|
257
|
+
rescue StandardError
|
|
258
|
+
nil
|
|
259
|
+
end
|
|
260
|
+
|
|
223
261
|
def colorize(level, line)
|
|
224
262
|
color = case level
|
|
225
263
|
when :debug then COLORS[:cyan]
|
data/lib/tina4/version.rb
CHANGED