lumberjack_redis_device 1.0.0

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