lumberjack_redis_device 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGE_LOG.md +3 -0
- data/MIT_LICENSE +20 -0
- data/README.md +22 -0
- data/VERSION +1 -0
- data/lib/lumberjack_redis_device.rb +130 -0
- data/lumberjack_redis_device.gemspec +36 -0
- metadata +133 -0
checksums.yaml
ADDED
@@ -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
|
data/CHANGE_LOG.md
ADDED
data/MIT_LICENSE
ADDED
@@ -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.
|
data/README.md
ADDED
@@ -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: []
|