Where should a gem store log files? - ruby

I am building a ruby gem that should output a logfile. Where is it a good practice to store log files?
I am extracting this functionality from a Rails website I am building, and there I could simply log in the log/ directory.

Ideally, make the path configurable (.rc file, switch, rails/rack config, whatever).
If it's a Rack middleware, add the possibility to specify it in the constructor's arguments.
If no log path is provided, fallback to detecting a log directory. (I vaguely remember it being config.paths['log'] in Rails, but be sure that config actually points to something before using that in your gem if it can be used outside of Rails.)
And if all else fails, log to nowhere...
Also, allow to disable logging if you enable it by default. Not everyone wants logs.

Related

Laravel 8: is it fine to leave unused functionality config files untouched in terms of performance, correctness and security?

Laravel 8 has config files for auth, mail, broadcasting, queue, services, session .etc, but I am not using those functionalities for my specific application.
Is it fine to leave the config files (and corresponding .env settings) untouched, or is it better to delete those files?
I am talking about both in terms of performance, execution correctness and security, but not in terms of code readability here. In other words I am talking about "real effects to my application".
Short answer:
it's not recommended to do something like that if you don't wanna go out from laravel's ecosystem.
TL;DR:
Since Laravel version 5.1 there was some general changes about the configurations. It means it for your v8 as well.
In every today's laravel project you have bootstrap/cache folder, which includes some bootstrap/cache/.gitignore file for ignoring other files. That ignored (3-4) files are actually cached files, which were creating automatically, and you can't do anything about that in-the-box.
The bootstrap/cache/config.php file is responsible for all the configurations, and it's creating as from config/*.php config files, as well as from all the config files from vendored dependencies. It means, everytime when you're using your laravel app, that file will be created automatically using
all the project-specific configurations
all the vendored configurations
environment variables from .env.
Note: there might be a case, when some in-box package (like laravel's default mail.php config file) or some 3rd-party package (unlikely, but anyway) could not have their own config file, so in vendor core codes there may be a confidence, that it can get some configs exactly from their apropriate config/*.php file, so in that case it's not recommended to delete that. For example, when you're deleting config/mail.php, and you're using that, in both cases you'll have approximately the same cached config, except some small mail-config-features (optimization there only approx. ~60 lines of human readable lines), but in that case you can't use laravel's Mailing functionality.
The sense is that when you want to override some configs, you're just creating some own config file(s) (in general with the same name as it's in vendor's appropriate location), so that laravel can do caching from config/*.php, but not from vendor/username/package/path/to/config.php.
So for optimization, laravel doing that caching process once, and after whole usage it will retrieve conifigs only from bootsrapped bootsrap/cache/config.php configs.
That's why everytime you're changing something in some config/*.php file or/and in .env file, you need to clean (manually) and it will be created again automatically
OR just:
there's a in-build command like:
# this will clean all the application caches
php artisan optimize
# or only for cleaning and recreating config
# this is an old-school version, but still used
php artisan config:cache
All this means, that you don't need to delete some config file from config/*.php, because laravel will check is the cached file exists, (if not, then it will create caches anyway from vendor configs), and all the time it will read them from cached files.
Conclusion: All this means, that
that is not related with security and there's nothing to do about that
if you feel that decreasing the cached bootstrap/config.php file content from 1566 lines to 1500 lines it's a way of optimization, then you're free to do that, but you should know that it could make some problems in future.
Subjective recommendation: in human language, i don't recommend to do something like that. Anyway you can do that, may you can improve something, that couldn't do another contributors yet. But it will not give a real effect to your app.

Ruby gem CLI tool, how should I save user settings?

I am currently making a CLI tool gem that downloads files from some service and saves them to a specified folder.
I was wondering, what would be the best way to store user settings for it?
For example, the folder to download the files to, the api access token and secret, that kind of thing.
I wouldn't want to ask a user for that input on every run.
I would read the API stuff from environment variables. Let the users decide if they want to enter it every time or set the variable in a .bashrc or .bash_profile file.
And I would ask for the download folder every time.

Topshelf, NLog and File Permissions

I have a Windows service application that uses the TopShelf library and I'm installing it in AWS during the cfn-init using the handy command line features that you get with topshelf.
C:\handy_service\> HandyService.exe install start
This basically installs the service in the registry and then calls sc start, but it's quite useful because it checks the service name matches what you expect and it allows you to configure the user that service will run as using the nice fluent API.
The installer code also writes some diagnostic logs to NLog if the service is configured to use NLog in general.
The problem is this: the installer runs as the default local administrator account that the AMI starts with and the NLog file gets created by this user. When the service starts up as the Network Service user, it doesn't have permission to write to the NLog log file.
How can I get my service to write to the log file? I've thought about setting the permissions programmatically but it looks nasty and I'd have to determine the log file name as this is generated dynamically based on the ec2 instance id. Also, it's not entirely obvious at what point the log file is first created. The easiest hack that I might go with is having two NLog.configs and switching one out at the end of the install after the logger is flushed. But because there is some overlap in time between the service starting and the installer exiting, I expect I'll lose a few lines of logging here.
Any clean suggestions would be greatly appreciated!
In the end I went with setting the permissions on the logs folder at deploy time. It's actually pretty straightforward with icacls, only a couple of lines in rake for instance, assuming you know where your logs folder is going to be:
sh %{icacls "#{logs_dir}" /grant "#{username}":(OI)(W)}
Not calling UseNLog() in the service config would also be a simple option, any install-time errors would go in the Windows event log in that case.

Customize Ruby Guardfile per User

I am using guard and therefore I have configured my Guardfile with my host's IP address where notifications should be sent.
How can I do this customization outside of the Guardfile so that only I can see it, not the rest of my team members?
From the shared configurations page in the Guard wiki:
If a .guard.rb is found in your home directory, it will be appended to
the Guardfile in your current directory. This can be used for tasks
you want guard to handle but other users probably don't.
You have several options -- you can either read the address from an environment variable or discern it with code. However, you can probably just use '127.0.0.1' which is the localhost address and should work for anyone to point to their own machine.

Ruby Gems with Persistent data

I want to create ruby application (not rails). This is a console app which will need to persist some data. I'm using pstore as the database. I want to deploy this application as a gem.
My question is: where does my data live?
Currently I've created a data directory as a sibling to the bin directory in a standard gem layout. I would therefore, expect that the gem would be storing its data "inside itself" after it gets deployed. But when I do a local gem install to test, I find that the data is being stored locally to the project files, not somewhere inside the gems directory.
Of course it could be I simply mis-understand what "rake install_gem" is doing. Also, I am vaguely worried that if I need to sudo to install the gem, that it will actually be able to create the data file "inside itself" in the gem directory.
Can someone clarify this a little bit?
Thank you.
John Schank
#makevoid - thanks for the reply. Here is the entirety of my main script. In /bin directory... (I added it to the main question because I'm not familiar with how to format content in a comment - and the pasted code looked awful.
#!/usr/bin/env ruby
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
require 'timesheet'
begin
command_hash = TimesheetParser.parse
store = YAML::Store.new("data/time_entries.yaml")
tl = TimeLog.new(store)
ts = Timesheet.new(tl)
ts.process(command_hash)
rescue Exception => e
raise if command_hash[:debug]
puts e.message
On Linux there are two common used locations for storing variable data.
/home/user/.application
If every user needs it's own storage this is usually done in the users home directory. The path for your storage in the users home directory should be
ENV["HOME"] + "/." + $application_name
/var/lib/application
If all users share the storage, or the application is intended to be run by only one user (most daemons), /var is the right place to store all kind of data.
/var/log for logs
/var/run for pid's
/var/lock for lock files
/var/www for httpservers
/var/tmp for not important but persistant data
/var/lib for all other data
The path for your storage in /var should be
"/var/lib/" + $application_name
Make sure, the permissions for this directory are such, that you don't have to let your application run as root.
You definitely don't want to store data inside the gem directory. The expected behaviour is that users can uninstall and reinstall gems without any problems. If you have data in your gem's installed directory, uninstalling the gem will destroy that data and piss off your users.
johannes has the right ideas for use on Linux. For a Mac the specific directories would be a little different. The same goes for Windows. You'll need to research what the right places are for each platform you want to target and have your code conditionally switch storage locations depending on what kind of host it runs on.
Don't forget to let users override your defaults. A way to do that will make them very happy :)

Resources