vector_mcp 0.3.1 → 0.3.2
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/CHANGELOG.md +68 -0
- data/lib/vector_mcp/errors.rb +6 -3
- data/lib/vector_mcp/handlers/core.rb +199 -45
- data/lib/vector_mcp/logger.rb +148 -0
- data/lib/vector_mcp/middleware/base.rb +177 -0
- data/lib/vector_mcp/middleware/context.rb +76 -0
- data/lib/vector_mcp/middleware/hook.rb +169 -0
- data/lib/vector_mcp/middleware/manager.rb +191 -0
- data/lib/vector_mcp/middleware.rb +43 -0
- data/lib/vector_mcp/security/strategies/jwt_token.rb +6 -3
- data/lib/vector_mcp/server.rb +61 -17
- data/lib/vector_mcp/session.rb +37 -4
- data/lib/vector_mcp/version.rb +1 -1
- data/lib/vector_mcp.rb +10 -35
- metadata +17 -24
- data/lib/vector_mcp/logging/component.rb +0 -131
- data/lib/vector_mcp/logging/configuration.rb +0 -156
- data/lib/vector_mcp/logging/constants.rb +0 -21
- data/lib/vector_mcp/logging/core.rb +0 -175
- data/lib/vector_mcp/logging/filters/component.rb +0 -69
- data/lib/vector_mcp/logging/filters/level.rb +0 -23
- data/lib/vector_mcp/logging/formatters/base.rb +0 -52
- data/lib/vector_mcp/logging/formatters/json.rb +0 -83
- data/lib/vector_mcp/logging/formatters/text.rb +0 -72
- data/lib/vector_mcp/logging/outputs/base.rb +0 -64
- data/lib/vector_mcp/logging/outputs/console.rb +0 -35
- data/lib/vector_mcp/logging/outputs/file.rb +0 -157
- data/lib/vector_mcp/logging.rb +0 -71
@@ -1,157 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "fileutils"
|
4
|
-
require "date"
|
5
|
-
|
6
|
-
module VectorMCP
|
7
|
-
module Logging
|
8
|
-
module Outputs
|
9
|
-
class File < Base
|
10
|
-
def initialize(config = {})
|
11
|
-
super
|
12
|
-
@path = @config[:path] or raise OutputError, "File path required"
|
13
|
-
@max_size = parse_size(@config[:max_size] || "100MB")
|
14
|
-
@max_files = @config[:max_files] || 7
|
15
|
-
@rotation = @config[:rotation] || "daily"
|
16
|
-
@mutex = Mutex.new
|
17
|
-
@file = nil
|
18
|
-
@current_date = nil
|
19
|
-
|
20
|
-
ensure_directory_exists
|
21
|
-
open_file
|
22
|
-
end
|
23
|
-
|
24
|
-
def close
|
25
|
-
@mutex.synchronize do
|
26
|
-
@file&.close
|
27
|
-
@file = nil
|
28
|
-
end
|
29
|
-
super
|
30
|
-
end
|
31
|
-
|
32
|
-
protected
|
33
|
-
|
34
|
-
def write_formatted(message)
|
35
|
-
@mutex.synchronize do
|
36
|
-
rotate_if_needed
|
37
|
-
@file.write(message)
|
38
|
-
@file.flush
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
def ensure_directory_exists
|
45
|
-
dir = ::File.dirname(@path)
|
46
|
-
FileUtils.mkdir_p(dir) unless ::File.directory?(dir)
|
47
|
-
rescue StandardError => e
|
48
|
-
raise OutputError, "Cannot create log directory #{dir}: #{e.message}"
|
49
|
-
end
|
50
|
-
|
51
|
-
def open_file
|
52
|
-
@file = ::File.open(current_log_path, "a")
|
53
|
-
@file.sync = true
|
54
|
-
@current_date = Date.today if daily_rotation?
|
55
|
-
rescue StandardError => e
|
56
|
-
raise OutputError, "Cannot open log file #{current_log_path}: #{e.message}"
|
57
|
-
end
|
58
|
-
|
59
|
-
def current_log_path
|
60
|
-
if daily_rotation?
|
61
|
-
base, ext = split_path(@path)
|
62
|
-
"#{base}_#{Date.today.strftime("%Y%m%d")}#{ext}"
|
63
|
-
else
|
64
|
-
@path
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def rotate_if_needed
|
69
|
-
return unless should_rotate?
|
70
|
-
|
71
|
-
rotate_file
|
72
|
-
open_file
|
73
|
-
end
|
74
|
-
|
75
|
-
def should_rotate?
|
76
|
-
return false unless @file
|
77
|
-
|
78
|
-
case @rotation
|
79
|
-
when "daily"
|
80
|
-
daily_rotation? && @current_date != Date.today
|
81
|
-
when "size"
|
82
|
-
@file.size >= @max_size
|
83
|
-
else
|
84
|
-
false
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def rotate_file
|
89
|
-
@file&.close
|
90
|
-
|
91
|
-
if daily_rotation?
|
92
|
-
cleanup_old_files
|
93
|
-
else
|
94
|
-
rotate_numbered_files
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def daily_rotation?
|
99
|
-
@rotation == "daily"
|
100
|
-
end
|
101
|
-
|
102
|
-
def rotate_numbered_files
|
103
|
-
return unless ::File.exist?(@path)
|
104
|
-
|
105
|
-
(@max_files - 1).downto(1) do |i|
|
106
|
-
old_file = "#{@path}.#{i}"
|
107
|
-
new_file = "#{@path}.#{i + 1}"
|
108
|
-
|
109
|
-
::File.rename(old_file, new_file) if ::File.exist?(old_file)
|
110
|
-
end
|
111
|
-
|
112
|
-
::File.rename(@path, "#{@path}.1")
|
113
|
-
end
|
114
|
-
|
115
|
-
def cleanup_old_files
|
116
|
-
base, ext = split_path(@path)
|
117
|
-
pattern = "#{base}_*#{ext}"
|
118
|
-
|
119
|
-
old_files = Dir.glob(pattern).reverse
|
120
|
-
files_to_remove = old_files[@max_files..] || []
|
121
|
-
|
122
|
-
files_to_remove.each do |file|
|
123
|
-
::File.unlink(file)
|
124
|
-
rescue StandardError => e
|
125
|
-
fallback_write("Warning: Could not remove old log file #{file}: #{e.message}\n")
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
def split_path(path)
|
130
|
-
ext = ::File.extname(path)
|
131
|
-
base = path.chomp(ext)
|
132
|
-
[base, ext]
|
133
|
-
end
|
134
|
-
|
135
|
-
def parse_size(size_str)
|
136
|
-
size_str = size_str.to_s.upcase
|
137
|
-
|
138
|
-
raise OutputError, "Invalid size format: #{size_str}" unless size_str =~ /\A(\d+)(KB|MB|GB)?\z/
|
139
|
-
|
140
|
-
number = ::Regexp.last_match(1).to_i
|
141
|
-
unit = ::Regexp.last_match(2) || "B"
|
142
|
-
|
143
|
-
case unit
|
144
|
-
when "KB"
|
145
|
-
number * 1024
|
146
|
-
when "MB"
|
147
|
-
number * 1024 * 1024
|
148
|
-
when "GB"
|
149
|
-
number * 1024 * 1024 * 1024
|
150
|
-
else
|
151
|
-
number
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
data/lib/vector_mcp/logging.rb
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "logging/constants"
|
4
|
-
require_relative "logging/core"
|
5
|
-
require_relative "logging/configuration"
|
6
|
-
require_relative "logging/component"
|
7
|
-
require_relative "logging/formatters/base"
|
8
|
-
require_relative "logging/formatters/text"
|
9
|
-
require_relative "logging/formatters/json"
|
10
|
-
require_relative "logging/outputs/base"
|
11
|
-
require_relative "logging/outputs/console"
|
12
|
-
require_relative "logging/outputs/file"
|
13
|
-
require_relative "logging/filters/level"
|
14
|
-
require_relative "logging/filters/component"
|
15
|
-
|
16
|
-
module VectorMCP
|
17
|
-
module Logging
|
18
|
-
class Error < StandardError; end
|
19
|
-
class ConfigurationError < Error; end
|
20
|
-
class FormatterError < Error; end
|
21
|
-
class OutputError < Error; end
|
22
|
-
|
23
|
-
LEVELS = {
|
24
|
-
TRACE: 0,
|
25
|
-
DEBUG: 1,
|
26
|
-
INFO: 2,
|
27
|
-
WARN: 3,
|
28
|
-
ERROR: 4,
|
29
|
-
FATAL: 5,
|
30
|
-
SECURITY: 6
|
31
|
-
}.freeze
|
32
|
-
|
33
|
-
LEVEL_NAMES = LEVELS.invert.freeze
|
34
|
-
|
35
|
-
def self.level_name(level)
|
36
|
-
(LEVEL_NAMES[level] || "UNKNOWN").to_s
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.level_value(name)
|
40
|
-
LEVELS[name.to_s.upcase.to_sym] || LEVELS[:INFO]
|
41
|
-
end
|
42
|
-
|
43
|
-
class LogEntry
|
44
|
-
attr_reader :timestamp, :level, :component, :message, :context, :thread_id
|
45
|
-
|
46
|
-
def initialize(attributes = {})
|
47
|
-
@timestamp = attributes[:timestamp]
|
48
|
-
@level = attributes[:level]
|
49
|
-
@component = attributes[:component]
|
50
|
-
@message = attributes[:message]
|
51
|
-
@context = attributes[:context] || {}
|
52
|
-
@thread_id = attributes[:thread_id]
|
53
|
-
end
|
54
|
-
|
55
|
-
def level_name
|
56
|
-
Logging.level_name(@level)
|
57
|
-
end
|
58
|
-
|
59
|
-
def to_h
|
60
|
-
{
|
61
|
-
timestamp: @timestamp.iso8601(Constants::TIMESTAMP_PRECISION),
|
62
|
-
level: level_name,
|
63
|
-
component: @component,
|
64
|
-
message: @message,
|
65
|
-
context: @context,
|
66
|
-
thread_id: @thread_id
|
67
|
-
}
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|