lokilogger 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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: []