observamax 1.0.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 881513afe14041c7127591b00fe015359aa367e53999e74ba50c6ca38ca8c52c
4
+ data.tar.gz: 37705065491662edfedd75257fa9501a2e4f06950a7d1f46e32980b2ffc8ad24
5
+ SHA512:
6
+ metadata.gz: 35f4951c5fe07359d62f1f5809e3bc57915d9fc92c6ce1214fefc611ce3098995ff19b950cdf1d6ac9b2fce3f13ac6ecc166e0158bda2f366db453f226f2e673
7
+ data.tar.gz: ccbd4c99488c31231e7af5d107e61e938a779667e6c3e0f4323b12ac3820d112202531a7ac54841df19ff4d7091c53879ec9b969526d684f9e4917f5e2dbe2c9
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ObservaMax
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,155 @@
1
+ # ObservaMax Ruby SDK
2
+
3
+ Official Ruby SDK for the ObservaMax API.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'observamax'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ ```bash
16
+ bundle install
17
+ ```
18
+
19
+ Or install it yourself:
20
+
21
+ ```bash
22
+ gem install observamax
23
+ ```
24
+
25
+ ## Quick Start
26
+
27
+ ```ruby
28
+ require 'observamax'
29
+
30
+ # Create client
31
+ client = Observamax::Client.new(api_key: "om_live_your_api_key")
32
+
33
+ # List all monitors
34
+ monitors = client.monitors.list
35
+ monitors.each do |monitor|
36
+ puts "#{monitor.name}: #{monitor.last_status}"
37
+ end
38
+ ```
39
+
40
+ ## Usage Examples
41
+
42
+ ### Monitors
43
+
44
+ ```ruby
45
+ # List monitors with pagination
46
+ monitors = client.monitors.list(page: 1, limit: 50)
47
+
48
+ # Get a specific monitor
49
+ monitor = client.monitors.get("monitor-id")
50
+
51
+ # Create a new monitor
52
+ monitor = client.monitors.create(
53
+ url: "https://api.example.com/health",
54
+ name: "My API",
55
+ check_interval: 5
56
+ )
57
+
58
+ # Update a monitor
59
+ monitor = client.monitors.update("monitor-id", name: "Updated Name")
60
+
61
+ # Pause/Resume a monitor
62
+ client.monitors.pause("monitor-id")
63
+ client.monitors.resume("monitor-id")
64
+
65
+ # Delete a monitor
66
+ client.monitors.delete("monitor-id")
67
+ ```
68
+
69
+ ### Alerts
70
+
71
+ ```ruby
72
+ # List all alerts
73
+ alerts = client.alerts.list
74
+
75
+ # Get a specific alert
76
+ alert = client.alerts.get("alert-id")
77
+
78
+ # Acknowledge an alert
79
+ alert = client.alerts.acknowledge("alert-id")
80
+
81
+ # Resolve an alert
82
+ alert = client.alerts.resolve("alert-id")
83
+ ```
84
+
85
+ ### Uptime Statistics
86
+
87
+ ```ruby
88
+ # Get uptime stats for all monitors
89
+ stats = client.uptime.get_stats(period: "7d") # 24h, 7d, or 30d
90
+
91
+ # Get uptime stats for a specific monitor
92
+ stats = client.uptime.get_monitor_stats("monitor-id", period: "30d")
93
+
94
+ puts "Uptime: #{stats.uptime}%"
95
+ puts "Avg Response: #{stats.avg_response_ms}ms"
96
+ ```
97
+
98
+ ## Configuration
99
+
100
+ ### Custom Base URL
101
+
102
+ ```ruby
103
+ client = Observamax::Client.new(
104
+ api_key: "api_key",
105
+ base_url: "https://custom.observamax.com/api/v1"
106
+ )
107
+ ```
108
+
109
+ ### Custom Timeout
110
+
111
+ ```ruby
112
+ client = Observamax::Client.new(
113
+ api_key: "api_key",
114
+ timeout: 60
115
+ )
116
+ ```
117
+
118
+ ## Error Handling
119
+
120
+ ```ruby
121
+ begin
122
+ monitor = client.monitors.get("invalid-id")
123
+ rescue Observamax::NotFoundError
124
+ puts "Monitor not found"
125
+ rescue Observamax::AuthenticationError
126
+ puts "Invalid API key"
127
+ rescue Observamax::RateLimitError => e
128
+ puts "Rate limited, retry after #{e.retry_after} seconds"
129
+ rescue Observamax::ValidationError => e
130
+ puts "Validation error: #{e.details}"
131
+ rescue Observamax::APIError => e
132
+ puts "API error (#{e.status_code}): #{e.message}"
133
+ end
134
+ ```
135
+
136
+ ## Pagination
137
+
138
+ ```ruby
139
+ # Iterate through all pages
140
+ page = 1
141
+ loop do
142
+ monitors = client.monitors.list(page: page, limit: 50)
143
+ break if monitors.data.empty?
144
+
145
+ monitors.each do |monitor|
146
+ puts monitor.name
147
+ end
148
+
149
+ page += 1
150
+ end
151
+ ```
152
+
153
+ ## License
154
+
155
+ MIT
@@ -0,0 +1,194 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+ require "uri"
5
+ require "json"
6
+
7
+ module Observamax
8
+ # HTTP client for the ObservaMax API
9
+ class Client
10
+ DEFAULT_BASE_URL = "https://observamax.com/api/v1"
11
+ DEFAULT_TIMEOUT = 30
12
+
13
+ attr_reader :monitors, :alerts, :uptime
14
+
15
+ def initialize(api_key:, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT)
16
+ raise ArgumentError, "API key is required" if api_key.nil? || api_key.empty?
17
+
18
+ @api_key = api_key
19
+ @base_url = base_url.chomp("/")
20
+ @timeout = timeout
21
+
22
+ @monitors = MonitorsAPI.new(self)
23
+ @alerts = AlertsAPI.new(self)
24
+ @uptime = UptimeAPI.new(self)
25
+ end
26
+
27
+ def request(method:, path:, params: nil, body: nil)
28
+ uri = build_uri(path, params)
29
+ request = build_request(method, uri, body)
30
+
31
+ response = execute_request(uri, request)
32
+ handle_response(response)
33
+ end
34
+
35
+ private
36
+
37
+ def build_uri(path, params)
38
+ uri = URI.parse("#{@base_url}#{path}")
39
+ if params && !params.empty?
40
+ uri.query = URI.encode_www_form(params.compact)
41
+ end
42
+ uri
43
+ end
44
+
45
+ def build_request(method, uri, body)
46
+ request_class = case method.to_s.upcase
47
+ when "GET" then Net::HTTP::Get
48
+ when "POST" then Net::HTTP::Post
49
+ when "PATCH" then Net::HTTP::Patch
50
+ when "DELETE" then Net::HTTP::Delete
51
+ else raise ArgumentError, "Unsupported HTTP method: #{method}"
52
+ end
53
+
54
+ request = request_class.new(uri)
55
+ request["Authorization"] = "Bearer #{@api_key}"
56
+ request["Content-Type"] = "application/json"
57
+ request["Accept"] = "application/json"
58
+ request.body = body.to_json if body
59
+
60
+ request
61
+ end
62
+
63
+ def execute_request(uri, request)
64
+ http = Net::HTTP.new(uri.host, uri.port)
65
+ http.use_ssl = uri.scheme == "https"
66
+ http.read_timeout = @timeout
67
+ http.open_timeout = @timeout
68
+ http.request(request)
69
+ end
70
+
71
+ def handle_response(response)
72
+ body = response.body ? JSON.parse(response.body) : nil
73
+
74
+ case response.code.to_i
75
+ when 200..299
76
+ body
77
+ when 401
78
+ raise AuthenticationError, body&.dig("error") || "Invalid or expired API key"
79
+ when 403
80
+ raise PermissionError, body&.dig("error") || "Permission denied"
81
+ when 404
82
+ raise NotFoundError, body&.dig("error") || "Resource not found"
83
+ when 429
84
+ retry_after = response["Retry-After"]&.to_i
85
+ raise RateLimitError.new(body&.dig("error") || "Rate limit exceeded", retry_after: retry_after)
86
+ when 400
87
+ raise ValidationError.new(body&.dig("error") || "Validation error", details: body&.dig("details"))
88
+ else
89
+ raise APIError.new(body&.dig("error") || "Request failed", status_code: response.code.to_i)
90
+ end
91
+ end
92
+ end
93
+
94
+ # Monitors API
95
+ class MonitorsAPI
96
+ def initialize(client)
97
+ @client = client
98
+ end
99
+
100
+ def list(page: nil, limit: nil)
101
+ response = @client.request(
102
+ method: :get,
103
+ path: "/monitors",
104
+ params: { page: page, limit: limit }
105
+ )
106
+ PaginatedResponse.new(data: response["data"], meta: response["meta"], model_class: Monitor)
107
+ end
108
+
109
+ def get(id)
110
+ response = @client.request(method: :get, path: "/monitors/#{id}")
111
+ Monitor.new(response)
112
+ end
113
+
114
+ def create(url:, **options)
115
+ body = { url: url }.merge(options)
116
+ response = @client.request(method: :post, path: "/monitors", body: body)
117
+ Monitor.new(response)
118
+ end
119
+
120
+ def update(id, **options)
121
+ response = @client.request(method: :patch, path: "/monitors/#{id}", body: options)
122
+ Monitor.new(response)
123
+ end
124
+
125
+ def delete(id)
126
+ @client.request(method: :delete, path: "/monitors/#{id}")
127
+ nil
128
+ end
129
+
130
+ def pause(id)
131
+ update(id, is_enabled: false)
132
+ end
133
+
134
+ def resume(id)
135
+ update(id, is_enabled: true)
136
+ end
137
+ end
138
+
139
+ # Alerts API
140
+ class AlertsAPI
141
+ def initialize(client)
142
+ @client = client
143
+ end
144
+
145
+ def list(page: nil, limit: nil)
146
+ response = @client.request(
147
+ method: :get,
148
+ path: "/alerts",
149
+ params: { page: page, limit: limit }
150
+ )
151
+ PaginatedResponse.new(data: response["data"], meta: response["meta"], model_class: Alert)
152
+ end
153
+
154
+ def get(id)
155
+ response = @client.request(method: :get, path: "/alerts/#{id}")
156
+ Alert.new(response)
157
+ end
158
+
159
+ def acknowledge(id)
160
+ response = @client.request(method: :post, path: "/alerts/#{id}/acknowledge")
161
+ Alert.new(response)
162
+ end
163
+
164
+ def resolve(id)
165
+ response = @client.request(method: :post, path: "/alerts/#{id}/resolve")
166
+ Alert.new(response)
167
+ end
168
+ end
169
+
170
+ # Uptime API
171
+ class UptimeAPI
172
+ def initialize(client)
173
+ @client = client
174
+ end
175
+
176
+ def get_stats(period: "24h")
177
+ response = @client.request(
178
+ method: :get,
179
+ path: "/uptime",
180
+ params: { period: period }
181
+ )
182
+ response.map { |item| UptimeStats.new(item) }
183
+ end
184
+
185
+ def get_monitor_stats(monitor_id, period: "24h")
186
+ response = @client.request(
187
+ method: :get,
188
+ path: "/monitors/#{monitor_id}/uptime",
189
+ params: { period: period }
190
+ )
191
+ UptimeStats.new(response)
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Observamax
4
+ # Base error class for all ObservaMax errors
5
+ class Error < StandardError; end
6
+
7
+ # Raised when authentication fails
8
+ class AuthenticationError < Error
9
+ def initialize(message = "Invalid or expired API key")
10
+ super
11
+ end
12
+ end
13
+
14
+ # Raised when the user lacks permission
15
+ class PermissionError < Error
16
+ def initialize(message = "Permission denied")
17
+ super
18
+ end
19
+ end
20
+
21
+ # Raised when a resource is not found
22
+ class NotFoundError < Error
23
+ def initialize(message = "Resource not found")
24
+ super
25
+ end
26
+ end
27
+
28
+ # Raised when rate limit is exceeded
29
+ class RateLimitError < Error
30
+ attr_reader :retry_after
31
+
32
+ def initialize(message = "Rate limit exceeded", retry_after: nil)
33
+ @retry_after = retry_after
34
+ super(message)
35
+ end
36
+ end
37
+
38
+ # Raised when request validation fails
39
+ class ValidationError < Error
40
+ attr_reader :details
41
+
42
+ def initialize(message = "Validation error", details: nil)
43
+ @details = details
44
+ super(message)
45
+ end
46
+ end
47
+
48
+ # Generic API error
49
+ class APIError < Error
50
+ attr_reader :status_code
51
+
52
+ def initialize(message, status_code: nil)
53
+ @status_code = status_code
54
+ super(message)
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Observamax
4
+ # Monitor status constants
5
+ module MonitorStatus
6
+ UP = "up"
7
+ DOWN = "down"
8
+ DEGRADED = "degraded"
9
+ PENDING = "pending"
10
+ end
11
+
12
+ # Monitor type constants
13
+ module MonitorType
14
+ HTTP = "http"
15
+ TCP = "tcp"
16
+ DNS = "dns"
17
+ PING = "ping"
18
+ HEARTBEAT = "heartbeat"
19
+ end
20
+
21
+ # Alert type constants
22
+ module AlertType
23
+ DOWN = "down"
24
+ UP = "up"
25
+ DEGRADED = "degraded"
26
+ CHANGE = "change"
27
+ end
28
+
29
+ # Alert severity constants
30
+ module AlertSeverity
31
+ INFO = "info"
32
+ WARNING = "warning"
33
+ CRITICAL = "critical"
34
+ end
35
+
36
+ # Base model class with attribute access
37
+ class Model
38
+ def initialize(attributes = {})
39
+ @attributes = {}
40
+ attributes.each do |key, value|
41
+ @attributes[key.to_s] = value
42
+ end
43
+ end
44
+
45
+ def [](key)
46
+ @attributes[key.to_s]
47
+ end
48
+
49
+ def to_h
50
+ @attributes.dup
51
+ end
52
+
53
+ def method_missing(method_name, *args)
54
+ key = method_name.to_s
55
+ if @attributes.key?(key)
56
+ @attributes[key]
57
+ else
58
+ super
59
+ end
60
+ end
61
+
62
+ def respond_to_missing?(method_name, include_private = false)
63
+ @attributes.key?(method_name.to_s) || super
64
+ end
65
+ end
66
+
67
+ # Represents a monitor
68
+ class Monitor < Model; end
69
+
70
+ # Represents an alert
71
+ class Alert < Model; end
72
+
73
+ # Represents uptime statistics
74
+ class UptimeStats < Model; end
75
+
76
+ # Represents a paginated response
77
+ class PaginatedResponse
78
+ attr_reader :data, :meta
79
+
80
+ def initialize(data:, meta:, model_class:)
81
+ @data = data.map { |item| model_class.new(item) }
82
+ @meta = meta
83
+ end
84
+
85
+ def total
86
+ meta["total"]
87
+ end
88
+
89
+ def page
90
+ meta["page"]
91
+ end
92
+
93
+ def limit
94
+ meta["limit"]
95
+ end
96
+
97
+ def each(&block)
98
+ @data.each(&block)
99
+ end
100
+
101
+ include Enumerable
102
+ end
103
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Observamax
4
+ VERSION = "1.0.0"
5
+ end
data/lib/observamax.rb ADDED
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "observamax/version"
4
+ require_relative "observamax/errors"
5
+ require_relative "observamax/models"
6
+ require_relative "observamax/client"
7
+
8
+ # ObservaMax SDK for Ruby
9
+ #
10
+ # @example Basic usage
11
+ # client = Observamax::Client.new(api_key: "om_live_...")
12
+ # monitors = client.monitors.list
13
+ # monitors.each do |monitor|
14
+ # puts "#{monitor.name}: #{monitor.last_status}"
15
+ # end
16
+ #
17
+ module Observamax
18
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: observamax
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - ObservaMax
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-01-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ description: Ruby client library for the ObservaMax website monitoring API. Monitor
28
+ uptime, track alerts, and manage your monitors programmatically.
29
+ email:
30
+ - support@observamax.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - LICENSE
36
+ - README.md
37
+ - lib/observamax.rb
38
+ - lib/observamax/client.rb
39
+ - lib/observamax/errors.rb
40
+ - lib/observamax/models.rb
41
+ - lib/observamax/version.rb
42
+ homepage: https://observamax.com
43
+ licenses:
44
+ - MIT
45
+ metadata:
46
+ homepage_uri: https://observamax.com
47
+ source_code_uri: https://github.com/observamax/sdk-ruby
48
+ documentation_uri: https://observamax.com/developers
49
+ changelog_uri: https://github.com/observamax/sdk-ruby/blob/main/CHANGELOG.md
50
+ post_install_message:
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: 2.7.0
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ requirements: []
65
+ rubygems_version: 3.0.3.1
66
+ signing_key:
67
+ specification_version: 4
68
+ summary: Official Ruby SDK for ObservaMax API
69
+ test_files: []