Class: OpenObserve::Search
- Defined in:
- lib/openobserve/search.rb
Overview
Log search and exploration.
The raw API makes a search verbose out of proportion to the question asked: the SQL has
to be wrapped in a SearchQuery inside a SearchSQLRequest, the window expressed in
microseconds, the organization repeated, and the rows dug out of a hits envelope. This
domain reduces all of that to "SQL plus a window".
Why this domain keeps using the typed sub-client
Every other domain issues raw connection.call(..., type: nil) requests, because the
generated sub-clients pin a model that both breaks Record#[] and drops undeclared
fields (see CLAUDE.md, "Hard rule"). Search is the documented exception: the socle
already passes type: nil for _search, _around and _values, so no model is ever
applied and the payload arrives intact. Going raw here would buy nothing and would mean
hand-serializing the SearchSQLRequest/SearchQuery body.
This holds only as long as those three operations stay untyped upstream. Nothing checks it statically — the e2e canary is what would catch a regression.
Constant Summary collapse
- DEFAULT_PAGE_SIZE =
100
Constants inherited from Resource
Instance Method Summary collapse
-
#all ⇒ Array<OpenObserve::Hit>
Every matching row, materialised.
-
#around(stream:, key:, size: 10, type: nil) ⇒ OpenObserve::SearchResult
The rows surrounding a given record — the "show me the context" view.
-
#each(sql:, from: nil, to: nil, last: nil, page_size: DEFAULT_PAGE_SIZE, now: Time.now, &block) ⇒ Enumerator<OpenObserve::Hit>
Auto-paginating iteration over every matching row.
-
#run(sql:, from: nil, to: nil, last: nil, size: DEFAULT_PAGE_SIZE, offset: 0, now: Time.now) ⇒ OpenObserve::SearchResult
Run one search.
-
#values(stream:, fields:, from: nil, to: nil, last: nil, size: 10, now: Time.now) ⇒ OpenObserve::SearchResult
Distinct values taken by one or more fields over a window — what populates a filter dropdown without scanning the rows yourself.
Methods inherited from Resource
Constructor Details
This class inherits a constructor from OpenObserve::Resource
Instance Method Details
#all ⇒ Array<OpenObserve::Hit>
Returns every matching row, materialised.
64 65 66 |
# File 'lib/openobserve/search.rb', line 64 def all(...) each(...).to_a end |
#around(stream:, key:, size: 10, type: nil) ⇒ OpenObserve::SearchResult
The rows surrounding a given record — the "show me the context" view.
74 75 76 77 78 79 80 |
# File 'lib/openobserve/search.rb', line 74 def around(stream:, key:, size: 10, type: nil) envelope = call do api._around(org_id: organization, stream_name: stream, key: key.to_s, size: size, type: type).data end SearchResult.from(envelope) end |
#each(sql:, from: nil, to: nil, last: nil, page_size: DEFAULT_PAGE_SIZE, now: Time.now, &block) ⇒ Enumerator<OpenObserve::Hit>
Auto-paginating iteration over every matching row.
55 56 57 58 59 60 61 |
# File 'lib/openobserve/search.rb', line 55 def each(sql:, from: nil, to: nil, last: nil, page_size: DEFAULT_PAGE_SIZE, now: Time.now, &block) enum = paginate(size: page_size) do |offset, size| run(sql: sql, from: from, to: to, last: last, size: size, offset: offset, now: now).hits end block ? enum.each(&block) : enum end |
#run(sql:, from: nil, to: nil, last: nil, size: DEFAULT_PAGE_SIZE, offset: 0, now: Time.now) ⇒ OpenObserve::SearchResult
Run one search.
41 42 43 44 45 46 47 48 49 |
# File 'lib/openobserve/search.rb', line 41 def run(sql:, from: nil, to: nil, last: nil, size: DEFAULT_PAGE_SIZE, offset: 0, now: Time.now) start_time, end_time = Coerce.window(from: from, to: to, last: last, now: now) envelope = call do api._search(org_id: organization, search_sql_request: request(sql, start_time, end_time, size, offset)).data end SearchResult.from(envelope) end |
#values(stream:, fields:, from: nil, to: nil, last: nil, size: 10, now: Time.now) ⇒ OpenObserve::SearchResult
Distinct values taken by one or more fields over a window — what populates a filter dropdown without scanning the rows yourself.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/openobserve/search.rb', line 87 def values(stream:, fields:, from: nil, to: nil, last: nil, size: 10, now: Time.now) start_time, end_time = Coerce.window(from: from, to: to, last: last, now: now) envelope = call do api._values( org_id: organization, stream_name: stream, fields: Array(fields).join(','), size: size, from: 0, start_time: start_time, end_time: end_time ).data end SearchResult.from(envelope) end |