lokilogger 0.5.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: 9d31b9a0ca62456df630504045404e80c8fdc08376afc0d6eb420457d9b0745b
4
+ data.tar.gz: '0283cd8fe736ecf933699b54d60f31a3e973d232c8794e8cdebff560624d7802'
5
+ SHA512:
6
+ metadata.gz: 338a081fc21929144d234674eb0cdaf64baf35e8fec2b9f84cf01f58acae1039ef6c9a6fcde6257126aee677ea21a6e4123f30246b9c020711d636955414d36f
7
+ data.tar.gz: eee408bb6e620234d75bee583aad338ae1200ce04d185027600bcd3d3ac4ac1bacd168002fc09abdfe52fca48baaee7d0a47d041351b1d29f3ae0f996370c33f
data/LICENSE.adoc ADDED
@@ -0,0 +1,23 @@
1
+ -= MIT License
2
+
3
+ MIT License
4
+
5
+ Copyright (c) 2023 Nils Bartels
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
data/README.adoc ADDED
@@ -0,0 +1,128 @@
1
+ :toc: macro
2
+ :toclevels: 5
3
+ :figure-caption!:
4
+
5
+ = lokilogger
6
+
7
+ toc::[]
8
+
9
+ == Features
10
+
11
+ Lokilogger is a gem to push logs to Grafana Loki. Some features:
12
+
13
+ - Push logs to Grafana Loki (either your own or Grafana Cloud)
14
+ - Push logs asynchronously
15
+
16
+ == Requirements
17
+
18
+ . link:https://www.ruby-lang.org[Ruby]
19
+ . link:https://grafana.com/oss/loki/[Grafana Loki]
20
+
21
+ == Setup
22
+
23
+ To install, run:
24
+
25
+ [source,bash]
26
+ ----
27
+ gem install lokilogger
28
+ ----
29
+
30
+ You can also add the gem directly to your project:
31
+
32
+ [source,bash]
33
+ ----
34
+ bundle add lokilogger
35
+ ----
36
+
37
+ Once the gem is installed, you only need to require it:
38
+
39
+ [source,ruby]
40
+ ----
41
+ require "lokilogger"
42
+ ----
43
+
44
+ == Rails
45
+
46
+ First off, regarding Ruby on Rails:
47
+
48
+ You can use Lokilogger within a Rails application. It has basic no-op implementations to make it compatible.
49
+ However, you are strongly adviced not use Lokilogger as your default logger in Rails.
50
+
51
+ Rails does not implement calls to Logger within Async do blocks and therefor calls to e.g. Lokilogger.info() will be executed synchronously.
52
+ That call will wait for the Loki Backend to respond. If you are using Grafana Cloud this means that any request that would produce some kind of
53
+ log message will wait for Grafana Cloud to respond. If you really want to use Lokilogger as Rails default logger please make sure
54
+ to have a Loki instance on the same network with low latency.
55
+
56
+ == Usage
57
+
58
+ Start by creating a new logger instance:
59
+
60
+ [source,ruby]
61
+ ----
62
+ # pass url, username, password
63
+ logger = Lokilogger.new({url:, log_level: 0, version: "v1", username:, password:, tags: {foo: "bar"}})
64
+ ----
65
+
66
+ If you need proxy or custom TLS settings, you can optionally pass as well:
67
+
68
+ - ssl_options (link:https://lostisland.github.io/faraday/#/customization/ssl-options[Faraday docs on ssl options])
69
+ - proxy_options (link:https://lostisland.github.io/faraday/#/customization/proxy-options[Farady docs on proxy options])
70
+
71
+ then it's straight forward:
72
+
73
+ [source,ruby]
74
+ ----
75
+ Async do
76
+ logger.debug("some debug", {useless: "tag"})
77
+ logger.info("an info", {useless: "tag"})
78
+ logger.warn("a warning", {useless: "tag"})
79
+ logger.error("an error", {useless: "tag"})
80
+ logger.fatal("a fatal", {useless: "tag"})
81
+ logger.unknown("into the unknown", {useless: "tag"})
82
+ end
83
+ ----
84
+
85
+ The second argument is extra_tags. This way you can pass custom tags per message. Be aware, that those cannot be nested.
86
+
87
+ To set the default log level:
88
+
89
+ [source,ruby]
90
+ ----
91
+ logger.level = 1
92
+ ----
93
+
94
+ Please see example/log.rb for an example implementation.
95
+
96
+ == Development
97
+
98
+ To contribute, run:
99
+
100
+ [source,bash]
101
+ ----
102
+ git clone
103
+ cd LokiLogger
104
+ bin/setup
105
+ ----
106
+
107
+ You can also use the IRB console for direct access to all objects:
108
+
109
+ [source,bash]
110
+ ----
111
+ bin/console
112
+ ----
113
+
114
+ == Tests
115
+
116
+ To test, run:
117
+
118
+ [source,bash]
119
+ ----
120
+ bin/rake
121
+ ----
122
+
123
+ == link:./LICENSE.adoc[License]
124
+
125
+ == Credits
126
+
127
+ * Built with link:https://alchemists.io/projects/gemsmith[Gemsmith].
128
+ * Really useful help by Stefan Piep.
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "async/http/faraday"
4
+ require "faraday"
5
+ require "lokilogger/error"
6
+
7
+ module Lokilogger
8
+ # the client
9
+ class Client
10
+ def initialize config
11
+ @config = config
12
+ check_config
13
+
14
+ ssl_options = @config[:ssl_options].nil? ? nil : @config[:ssl_options]
15
+ proxy_options = @config[:proxy_options].nil? ? nil : @config[:proxy_options]
16
+ request_options = {timeout: 10, open_timeout: 10, read_timeout: 10, write_timeout: 10}
17
+
18
+ Faraday.default_adapter = :async_http
19
+ @conn = Faraday.new url: @config[:url], headers: {"Content-Type" => "application/json"}, ssl: ssl_options, proxy: proxy_options, request: request_options do |builder|
20
+ builder.request :authorization, :basic, @config[:username], @config[:password]
21
+ end
22
+ end
23
+
24
+ def check_config
25
+ fail ConfigError, "missing/malformed url in config" if !@config[:url] || @config[:url] !~ %r{^(http|https)://}
26
+ fail ConfigError, "missing version in config" unless @config[:version]
27
+ fail ConfigError, "missing auth username in config" unless @config[:username]
28
+ fail ConfigError, "missing auth password in config" unless @config[:password]
29
+ fail ConfigError, "missing tags in config" unless @config[:tags]
30
+ fail ConfigError, "missing log_level in config" unless @config[:log_level]
31
+ end
32
+
33
+ def log_level
34
+ @config[:log_level]
35
+ end
36
+
37
+ def log_level= log_level
38
+ @config[:log_level] = log_level
39
+ end
40
+
41
+ def request severity, message, extra_tags
42
+ now = Time.now
43
+ rational_seconds = now.to_r
44
+ timestamp = (rational_seconds * (10**9)).to_i.to_s
45
+
46
+ tags = @config[:tags]
47
+ tags = tags.merge extra_tags unless extra_tags.nil?
48
+ tags = tags.merge({severity:})
49
+
50
+ Async do
51
+ @conn.post "/loki/api/#{@config[:version]}/push" do |req|
52
+ body = {streams: [{stream: tags, values: [[timestamp, message]]}]}.to_json
53
+
54
+ req.body = body
55
+ end
56
+ rescue Faraday::Error => error
57
+ puts error.response[:status]
58
+ puts error.response[:body]
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lokilogger
4
+ # the default error
5
+ class Error < StandardError
6
+ end
7
+
8
+ # something is wrong with the config
9
+ class ConfigError < Error
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Main namespace.
4
+ module Lokilogger
5
+ VERSION = "0.5.0"
6
+ end
data/lib/lokilogger.rb ADDED
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "zeitwerk"
4
+
5
+ Zeitwerk::Loader.new.then do |loader|
6
+ loader.tag = File.basename __FILE__, ".rb"
7
+ loader.push_dir __dir__
8
+ loader.setup
9
+ end
10
+
11
+ # Main namespace.
12
+ module Lokilogger
13
+ def self.loader registry = Zeitwerk::Registry
14
+ @loader ||= registry.loaders.find { |loader| loader.tag == File.basename(__FILE__, ".rb") }
15
+ end
16
+
17
+ def self.new config
18
+ @client = Lokilogger::Client.new config
19
+ self
20
+ end
21
+
22
+ def self.debug(*args)
23
+ message "debug", args
24
+ end
25
+
26
+ def self.debug?
27
+ true
28
+ end
29
+
30
+ def self.info(*args)
31
+ message "info", args
32
+ end
33
+
34
+ def self.info?
35
+ true
36
+ end
37
+
38
+ def self.warn(*args)
39
+ message "warn", args
40
+ end
41
+
42
+ def self.warn?
43
+ true
44
+ end
45
+
46
+ def self.error(*args)
47
+ message "error", args
48
+ end
49
+
50
+ def self.error?
51
+ true
52
+ end
53
+
54
+ def self.fatal(*args)
55
+ message "fatal", args
56
+ end
57
+
58
+ def self.fatal?
59
+ true
60
+ end
61
+
62
+ def self.unknown(*args)
63
+ message "unknown", args
64
+ end
65
+
66
+ def self.unknown?
67
+ true
68
+ end
69
+
70
+ def self.level= level
71
+ @client.log_level = level
72
+ end
73
+
74
+ def self.level
75
+ @client.log_level
76
+ end
77
+
78
+ def self.formatter
79
+ end
80
+
81
+ def self.formatter=(*args)
82
+ end
83
+
84
+ def self.message(severity, *args)
85
+ message = args[0][0]
86
+ extra_tags = args[0][1] if args[0].count > 1
87
+
88
+ @client.request severity, message, extra_tags
89
+ end
90
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path "lib", __dir__
4
+ $LOAD_PATH.unshift lib unless $LOAD_PATH.include? lib
5
+ require "lokilogger/version"
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "lokilogger"
9
+ spec.version = Lokilogger::VERSION
10
+ spec.authors = ["Nils Bartels"]
11
+ spec.email = ["rubygems@nils.bartels.xyz"]
12
+ spec.homepage = "https://gitlab.com/sukunai/lokilogger"
13
+ spec.summary = "Log asynchronously to Grafana Loki"
14
+ spec.license = "MIT"
15
+
16
+ spec.metadata = {"label" => "lokilogger", "rubygems_mfa_required" => "true"}
17
+
18
+ #spec.signing_key = Gem.default_key_path
19
+ #spec.cert_chain = [Gem.default_cert_path]
20
+
21
+ spec.required_ruby_version = "~> 3.2"
22
+ spec.add_dependency "async", "~> 2.6", ">= 2.6.5"
23
+ spec.add_dependency "async-http-faraday", "~> 0.12.0"
24
+ spec.add_dependency "faraday", "~> 2.7", ">= 2.7.12"
25
+ spec.add_dependency "refinements", "~> 11.0"
26
+ spec.add_dependency "zeitwerk", "~> 2.6"
27
+
28
+ spec.extra_rdoc_files = Dir["README*", "LICENSE*"]
29
+ spec.files = Dir["*.gemspec", "lib/**/*"]
30
+ end
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lokilogger
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
+ platform: ruby
6
+ authors:
7
+ - Nils Bartels
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-12-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: async
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.6'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.6.5
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '2.6'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.6.5
33
+ - !ruby/object:Gem::Dependency
34
+ name: async-http-faraday
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 0.12.0
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 0.12.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: faraday
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '2.7'
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: 2.7.12
57
+ type: :runtime
58
+ prerelease: false
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - "~>"
62
+ - !ruby/object:Gem::Version
63
+ version: '2.7'
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: 2.7.12
67
+ - !ruby/object:Gem::Dependency
68
+ name: refinements
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '11.0'
74
+ type: :runtime
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '11.0'
81
+ - !ruby/object:Gem::Dependency
82
+ name: zeitwerk
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '2.6'
88
+ type: :runtime
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: '2.6'
95
+ description:
96
+ email:
97
+ - rubygems@nils.bartels.xyz
98
+ executables: []
99
+ extensions: []
100
+ extra_rdoc_files:
101
+ - README.adoc
102
+ - LICENSE.adoc
103
+ files:
104
+ - LICENSE.adoc
105
+ - README.adoc
106
+ - lib/lokilogger.rb
107
+ - lib/lokilogger/client.rb
108
+ - lib/lokilogger/error.rb
109
+ - lib/lokilogger/version.rb
110
+ - lokilogger.gemspec
111
+ homepage: https://gitlab.com/sukunai/lokilogger
112
+ licenses:
113
+ - MIT
114
+ metadata:
115
+ label: lokilogger
116
+ rubygems_mfa_required: 'true'
117
+ post_install_message:
118
+ rdoc_options: []
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - "~>"
124
+ - !ruby/object:Gem::Version
125
+ version: '3.2'
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ requirements: []
132
+ rubygems_version: 3.4.22
133
+ signing_key:
134
+ specification_version: 4
135
+ summary: Log asynchronously to Grafana Loki
136
+ test_files: []