lumberjack_redis_device 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0bbc9ce42f70e40c813a3d446f7a185d876d5a1475179b9fb58286d0648f7293
4
+ data.tar.gz: 790abe1f48c28198df3584184ac336a87ea399102f1f6b381786e16de40b114f
5
+ SHA512:
6
+ metadata.gz: 2bde67b21c182c709faa85c6ee49b1b39afa063a61eee3563d3e02aaeaad4a98a07951eee02595d7296b155b3824db184272b9def616ff3238d3fa42c1010914
7
+ data.tar.gz: 9150565938e10b012aeec942cc81d244280abfa01c91c117144ce8cd0c17749ef98736d4a68656369fc1a3dbc20bfc4393fd3fd6cd5ec8299ab434b016bab6c2
@@ -0,0 +1,3 @@
1
+ # 1.0.0
2
+
3
+ * Initial release
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2020 Brian Durand
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,22 @@
1
+ # Lumberjack Redis Device
2
+
3
+ [![Build Status](https://travis-ci.org/bdurand/lumberjack_redis_device.svg?branch=master)](https://travis-ci.org/bdurand/lumberjack_redis_device)
4
+ [![Maintainability](https://api.codeclimate.com/v1/badges/7785eba72f9a92b686b2/maintainability)](https://codeclimate.com/github/bdurand/lumberjack_redis_device/maintainability)
5
+
6
+ This is a simple reference implementation of a device for the [lumberjack](https://github.com/bdurand/lumberjack) to send logs to a data store.
7
+
8
+ Log data will be stored in a Redis list. This will likely not scale to handle permanent or large log storage, but it can be useful as a temporary store in log shipment, or as a debug tool for seeing only recent log entries.
9
+
10
+ The number of entries in the list can be capped with the `:limit` paramter on the constructor. An expiration time can also be set on the redis key as well with the `:ttl` parameter.
11
+
12
+ ```ruby
13
+ # create a device to save to the app.log key in redis
14
+ # with a limit of 1000 entries that expires one hour after the last write.
15
+ device = Lumberjack::RedisDevice.new("app.log", redis: Redis.new, limit: 1000, ttl: 3600)
16
+ ```
17
+
18
+ The log entries can then be read out again with the `read` method. The result will be an array of `Lumberjack::LogEntry` objects in the reverse order that they were written in (i.e. newest first).
19
+
20
+ ```ruby
21
+ entries = device.read
22
+ ```
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lumberjack'
4
+ require 'multi_json'
5
+ require 'redis'
6
+
7
+ module Lumberjack
8
+ # This Lumberjack device logs output to a redis list. The redis list will automatically truncate
9
+ # to a given size to prevent running out of memory on the server. This is not inteneded to be a
10
+ # scalable logging solution, but it can be useful as an additional logging tool to expose recent logs.
11
+ class RedisDevice < Device
12
+
13
+ attr_reader :name, :ttl, :limit
14
+
15
+ # Create a device. The name will be used as the key for the log entris in redis.
16
+ #
17
+ # The redis object can either be a `Redis` instance or a block that yields a `Redis`
18
+ # instance.
19
+ #
20
+ # You can also specify a time to live in seconds (ttl) and set the limit for the size of the list.
21
+ def initialize(name:, redis:, limit: 10_000, ttl: nil)
22
+ @name = name
23
+ @redis = redis
24
+ @ttl = ttl.to_i
25
+ @limit = limit
26
+ end
27
+
28
+ # Write an entry to the list in redis
29
+ def write(entry)
30
+ data = entry_as_json(entry)
31
+ json = MultiJson.dump(data)
32
+ redis.multi do |transaction|
33
+ transaction.lpush(name, json)
34
+ transaction.ltrim(name, 0, limit - 1)
35
+ transaction.expire(name, ttl) if ttl && ttl > 0
36
+ end
37
+ end
38
+
39
+ # Read a set number of entries from the list. The result will be an array of
40
+ # Lumberjack::LogEntry objects.
41
+ def read(count = limit)
42
+ docs = redis.lrange(name, 0, count - 1)
43
+ docs.collect { |json| entry_from_json(json) }
44
+ end
45
+
46
+ def datetime_format
47
+ @time_formatter.format if @time_formatter
48
+ end
49
+
50
+ def datetime_format=(format)
51
+ @time_formatter = Lumberjack::Formatter::DateTimeFormatter.new(format)
52
+ end
53
+
54
+ def redis
55
+ if @redis.is_a?(Proc)
56
+ @redis.call
57
+ else
58
+ @redis
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ def entry_as_json(entry)
65
+ data = {}
66
+ set_attribute(data, "timestamp", entry.time.to_f) unless entry.time.nil?
67
+ set_attribute(data, "time", entry.time)
68
+ set_attribute(data, "severity", entry.severity_label)
69
+ set_attribute(data, "progname", entry.progname)
70
+ set_attribute(data, "pid", entry.pid)
71
+ set_attribute(data, "message", entry.message)
72
+ set_attribute(data, "tags", entry.tags)
73
+
74
+ unless @tags_key.nil?
75
+ tags ||= {}
76
+ set_attribute(data, @tags_key, tags)
77
+ end
78
+
79
+ data = @formatter.format(data) if @formatter
80
+ data
81
+ end
82
+
83
+ def entry_from_json(json)
84
+ data = MultiJson.load(json)
85
+ time = Time.at(data["timestamp"]) if data["timestamp"]
86
+ severity = data["severity"]
87
+ progname = data["progname"]
88
+ pid = data["pid"]
89
+ message = data["message"]
90
+ tags = data["tags"]
91
+ LogEntry.new(time, severity, message, progname, pid, tags)
92
+ end
93
+
94
+ def set_attribute(data, key, value)
95
+ return if value.nil?
96
+
97
+ if (value.is_a?(Time) || value.is_a?(DateTime)) && @time_formatter
98
+ value = @time_formatter.call(value)
99
+ end
100
+
101
+ if key.is_a?(Array)
102
+ unless key.empty?
103
+ if key.size == 1
104
+ data[key.first] = value
105
+ else
106
+ data[key.first] ||= {}
107
+ set_attribute(data[key.first], key[1, key.size], value)
108
+ end
109
+ end
110
+ elsif key.respond_to?(:call)
111
+ hash = key.call(value)
112
+ if hash.is_a?(Hash)
113
+ data.merge!(Lumberjack::Tags.stringify_keys(hash))
114
+ end
115
+ else
116
+ data[key] = value unless key.nil?
117
+ end
118
+ end
119
+
120
+ def default_formatter
121
+ formatter = Formatter.new.clear
122
+ object_formatter = Lumberjack::Formatter::ObjectFormatter.new
123
+ formatter.add(String, object_formatter)
124
+ formatter.add(Object, object_formatter)
125
+ formatter.add(Enumerable, Formatter::StructuredFormatter.new(formatter))
126
+ formatter.add(Exception, Formatter::InspectFormatter.new)
127
+ end
128
+
129
+ end
130
+ end
@@ -0,0 +1,36 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = 'lumberjack_redis_device'
3
+ spec.version = File.read(File.expand_path("../VERSION", __FILE__)).strip
4
+ spec.authors = ['Brian Durand']
5
+ spec.email = ['bbdurand@gmail.com']
6
+
7
+ spec.summary = "A logging device for the lumberjack gem that writes log entries as JSON documentspec."
8
+ spec.homepage = "https://github.com/bdurand/lumberjack_redis_device"
9
+ spec.license = "MIT"
10
+
11
+ # Specify which files should be added to the gem when it is released.
12
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
13
+ ignore_files = %w(
14
+ .gitignore
15
+ .travis.yml
16
+ Appraisals
17
+ Gemfile
18
+ Gemfile.lock
19
+ Rakefile
20
+ gemfiles/
21
+ spec/
22
+ )
23
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
24
+ `git ls-files -z`.split("\x0").reject{ |f| ignore_files.any?{ |path| f.start_with?(path) } }
25
+ end
26
+
27
+ spec.require_paths = ['lib']
28
+
29
+ spec.add_dependency "lumberjack", ">=1.1"
30
+ spec.add_dependency "multi_json"
31
+ spec.add_dependency "redis"
32
+
33
+ spec.add_development_dependency("rspec", ["~> 3.0"])
34
+ spec.add_development_dependency "rake"
35
+ spec.add_development_dependency "fakeredis"
36
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lumberjack_redis_device
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Brian Durand
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-01-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: lumberjack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '1.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: multi_json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: redis
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: fakeredis
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description:
98
+ email:
99
+ - bbdurand@gmail.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - CHANGE_LOG.md
105
+ - MIT_LICENSE
106
+ - README.md
107
+ - VERSION
108
+ - lib/lumberjack_redis_device.rb
109
+ - lumberjack_redis_device.gemspec
110
+ homepage: https://github.com/bdurand/lumberjack_redis_device
111
+ licenses:
112
+ - MIT
113
+ metadata: {}
114
+ post_install_message:
115
+ rdoc_options: []
116
+ require_paths:
117
+ - lib
118
+ required_ruby_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ required_rubygems_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ requirements: []
129
+ rubygems_version: 3.0.3
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: A logging device for the lumberjack gem that writes log entries as JSON documentspec.
133
+ test_files: []