defining a custom logger in grails 3 using logback - logback

I want to define a different logger from the default to log things in a different file. I've try to define a custom logger. The file is created but grails never logs anything.
appender("APPENDER", FileAppender) {
file = "logs/info.log"
append = true
encoder(PatternLayoutEncoder) {
pattern = "%level - %msg%n"
}
}
logger("logger", INFO, ['APPENDER'], false)
Then in a controller I want to call it using: log.info "something" but nothing is written.

This contains daily rolling policy and max size of the log file. The catch is /var/logs should have a write access.
def currentDay = timestamp("yyyyMMdd")
appender(FILE, RollingFileAppender) {
file = "/var/logs/info_${currentDay}.log"
rollingPolicy(FixedWindowRollingPolicy) {
fileNamePattern = "/var/logs/info_${currentDay}.%i.log"
minIndex = 1
maxIndex = 9
}
triggeringPolicy(SizeBasedTriggeringPolicy) {
maxFileSize = "50MB"
}
encoder(PatternLayoutEncoder) {
pattern = "%level %date %logger - %msg%n"
}
append = true
}
Note: your user should have a write access to /var/logs/

Add: import static ch.qos.logback.classic.Level.INFO
Where: conf/logback.groovy file
Thanks "nayan kakati" I've figured out earlier!

Related

How do I use s3 lifeycle rules in Terraform in a modular form, i.e. referenced in separate JSON?

Currently, I'm specifying lifecycle_rule under my s3 resource:
resource "aws_s3_bucket" "bucket-name" {
bucket = "bucket-name"
lifecycle_rule {
id = "Expiration Rule"
enabled = true
prefix = "reports/"
expiration {
days = 30
}
}
}
...but I imagine there must be a way to make this more modular, like putting the lifecycle rule into a separate JSON so I can reference it for multiple s3 buckets and reduce the need to edit each resource. I know how to do this in general and have done this with other resources as seen here:
resource "aws_iam_policy" "devops-admin-write" {
name = "devops-admin-s3"
description = "Devops-Admin group s3 policy."
policy = file("iam_policies/devops-admin-write.json")
}
...the difference is that "lifecycle_rule" is an argument and not an attribute - and it's not clear to me how to make it work. Google-Fu has not yielded any clear answers either.
You can use dynamic blocks that you execute with a generic local variable.
So you just need to change the local variable and changes will reflect in all places where this variable is used.
To make it more maintainable I would suggest building a module and reusing the module or using an exiting module.
But the locals + dynamic implementation could look like this:
locals {
lifecycle_rules = [
{
id = "Expiration Rule"
enabled = true
prefix = "reports/"
expiration = {
days = 30
}
}
]
}
resource "aws_s3_bucket" "bucket-name" {
bucket = "bucket-name"
dynamic "lifecycle_rule" {
for_each = local.lifecycle_rules
content {
id = lifecycle_rule.each.id
enabled = lifecycle_rule.each.enabled
prefix = lifecycle_rule.each.prefix
expiration {
days = lifecycle_rule.each.expiration.days
}
}
}
}
This does not check for errors and is not complete of course - it just implements your example.
See a more complete generic example in our terraform s3-bucket module: find code here

Gradle : How to use task's output file data in another task?

Problematic
I want to update html files before packagind in war to set an HASH variable corresponding to a JS bundle compilation.
Here is what I have
<script th:src="#{/static/js/assistance/manifest.js}" charset="UTF-8"></script>
Here is what I want at the end of the process
<script th:src="#{/static/js/assistance/manifest.hereIsTheHash.js}" charset="UTF-8"></script>
The hash is generated after the JS compilation which is a gradle task (see below) and is stored in a json file created after the compilation.
What I've tried (after a thousand of another try)
In order to update all my HTML files with a reference to my JS with HASH, I've tried this :
war{
dependsOn 'createStatsJson'
filesMatching('WEB-INF/views/**.html'){
filter { String line ->
line = line.replaceAll('assistance.js', ext.assistanceJs)
line = line.replaceAll('manifest.js', ext.manifestJs)
line = line.replaceAll('vendor.js', ext.vendorJs)
}
}
}
If I replace ext.assistanceJs, ext.manifestJs or ext.vendorJs by a string, it works perfectly.
These variables are defined in another task which read a json file :
task createStatsJson(dependsOn: 'buildAssistanceJS') {
def jsonFile = file('build/webpack/assistance/stats.json')
def parsedJson = new groovy.json.JsonSlurper().parseText(jsonFile.text)
ext.assistanceJs = parsedJson.assetsByChunkName.assistance[0]
ext.manifestJs = parsedJson.assetsByChunkName.manifest
ext.vendorJs = parsedJson.assetsByChunkName.vendor
}
This json file is created by another task :
task buildAssistanceJS(dependsOn: 'gulp_less', type: NpmTask) {
args = ['--prefix', 'src/main/javascript/assistance', 'run', 'build']
}
Problem
Unfortunately, it don't works as gradle tels me that the json file does not exists. I supposed it's an build lifecycle related problem but I don't know how to achive this.
Any help is greatly appreciated.
task createStatsJson(dependsOn: 'buildAssistanceJS') {
def jsonFile = file('build/webpack/assistance/stats.json')
def parsedJson = new groovy.json.JsonSlurper().parseText(jsonFile.text)
ext.assistanceJs = parsedJson.assetsByChunkName.assistance[0]
ext.manifestJs = parsedJson.assetsByChunkName.manifest
ext.vendorJs = parsedJson.assetsByChunkName.vendor
}
This is a configuration closure of the createStatsJson task, not the execution phase.
See Gradle build lifecycle for more information.
Essentially, when that piece of code executes - there is still no build/.../stats.json (unless it's there from a previous build and you're not using the clean task).
You need to change this task to
task createStatsJson(dependsOn: 'buildAssistanceJS') {
doLast {
def jsonFile = file('build/webpack/assistance/stats.json')
def parsedJson = new groovy.json.JsonSlurper().parseText(jsonFile.text)
ext.assistanceJs = parsedJson.assetsByChunkName.assistance[0]
ext.manifestJs = parsedJson.assetsByChunkName.manifest
ext.vendorJs = parsedJson.assetsByChunkName.vendor
}
}
This will provide values in the ex.* variables in the execution phase.
I assume that createStatsJson has an explicit dependency on the relevant build tasks so that the stats.json (buildAssistanceJS I guess) file will be present when executed.
Your war task code suffers from the same problem. the code runs in the configuration phase, not the execution phase.
war{
dependsOn 'createStatsJson'
doLast {
filesMatching('WEB-INF/views/**.html'){
filter { String line ->
line = line.replaceAll('assistance.js', ext.assistanceJs)
line = line.replaceAll('manifest.js', ext.manifestJs)
line = line.replaceAll('vendor.js', ext.vendorJs)
}
}
}
}
Finally found a working solution. Hope it will help.
task buildAssistanceJS(dependsOn: 'gulp_less', type: NpmTask) {
args = ['--prefix', 'src/main/javascript/assistance', 'run', 'build']
}
def assistanceJs = ""
def manifestJs = ""
def vendorJs = ""
task createStatsJson(dependsOn: 'buildAssistanceJS') {
doLast {
def jsonFile = file('build/webpack/assistance/stats.json')
def parsedJson = new groovy.json.JsonSlurper().parseText(jsonFile.text)
assistanceJs = parsedJson.assetsByChunkName.assistance[0]
manifestJs = parsedJson.assetsByChunkName.manifest
vendorJs = parsedJson.assetsByChunkName.vendor
}
}
war {
dependsOn 'createStatsJson'
filesMatching('WEB-INF/views/**.html'){ fichier ->
fichier.filter { String line ->
line = line.replaceAll('assistance.js', assistanceJs)
line = line.replaceAll('manifest.js', manifestJs)
line = line.replaceAll('vendor.js', vendorJs)
}
}
}

JSON report not generating for failed scenarios using protractor

If my scenarios got failed the JSON report not generating. But for passes scenarios I can able to see the JSON report.
Please find my config file as below.
In comment prompt console I can able to see the failure message:
W/launcher - Ignoring uncaught error AssertionError: expected false to equal true
E/launcher - BUG: launcher exited with 1 tasks remaining
You can save the report by using a hook, so don't generate the file form the protractor.conf.js file, but use a cucumber-hook for it.
The hook can look like this
reportHook.js:
const cucumber = require('cucumber');
const jsonFormatter = cucumber.Listener.JsonFormatter();
const fs = require('fs-extra');
const jsonFile = require('jsonfile');
const path = require('path');
const projectRoot = process.cwd();
module.exports = function reportHook() {
this.registerListener(jsonFormatter);
/**
* Generate and save the report json files
*/
jsonFormatter.log = function(report) {
const jsonReport = JSON.parse(report);
// Generate a featurename without spaces, we're gonna use it later
const featureName = jsonReport[0].name.replace(/\s+/g, '_').replace(/\W/g, '').toLowerCase();
// Here I defined a base path to which the jsons are written to
const snapshotPath = path.join(projectRoot, '.tmp/json-output');
// Think about a name for the json file. I now added a featurename (each feature
// will output a file) and a timestamp (if you use multiple browsers each browser
// execute each feature file and generate a report)
const filePath = path.join(snapshotPath, `report.${featureName}.${new Date}.json`);
// Create the path if it doesn't exists
fs.ensureDirSync(snapshotPath);
// Save the json file
jsonFile.writeFileSync(filePath, jsonReport, {
spaces: 2
});
};
}
You can save this code to the file reportHook.js and then add it to the cucumberOpts:.require so it will look like this in your code
cucumberOpts: {
require: [
'../step_definitions/*.json',
'../setup/hooks.js',
'../setup/reportHook.js'
],
....
}
Even with failed steps / scenario's it should generate the report file.
Hope it helps

AWS Lambda function - can't call update thing shadow

According to boto3 documentation here: https://boto3.readthedocs.org/en/latest/reference/services/iot-data.html#client the update_thing_shadow method takes the thingName & JSON payload as parameters. Currently it reads:
client = boto3.client('iot-data', region_name='us-east-1')
data = {"state" : { "desired" : { "switch" : "on" }}}
mypayload = json.dumps(data)
response = client.update_thing_shadow(
thingName = 'MyDevice',
payload = b'mypayload'
)
When I use the command line there's no problem but can't seem to get it right from within the lamba function. I've called it with numerous versions of code (json.JSONEncoder, bytearray(), etc..) without any luck. The errors range from syntax to (ForbiddenException) when calling the UpdateThingShadow operation: Bad Request: ClientError. Has anyone had success calling this or a similar method from within a AWS lambda function? Thanks.
This code is working fine for me:
def set_thing_state(thingName, state):
# Change topic, qos and payload
payload = json.dumps({'state': { 'desired': { 'property': state } }})
logger.info("IOT update, thingName:"+thingName+", payload:"+payload)
#payload = {'state': { 'desired': { 'property': state } }}
response = client.update_thing_shadow(
thingName = thingName,
payload = payload
)
logger.info("IOT response: " + str(response))
logger.info("Body:"+response['payload'].read())
def get_thing_state(thingName):
response = client.get_thing_shadow(thingName=thingName)
streamingBody = response["payload"]
jsonState = json.loads(streamingBody.read())
print jsonState
#print jsonState["state"]["reported"]
Good luck
garnaat is right.
Just replace payload = b'mypayload' with payload = mypayload and it should work.

How can I update an existing JSON object's parameters in Grails?

I'm making a todo list. When first entering the item and adding it to the list, the server works great. It takes the parameters that the user selects and passes them into a list on the server that can be viewed by rendering Item.list(), that looks like so:
[{"class":"server.Item","id":1,"assignedTo":"User 1","comments":null,"completed":false,"creator":"User 1","name":"Task 1","priority":"1","type":"Personal"},
{"class":"server.Item","id":2,"assignedTo":"User 2","comments":null,"completed":false,"creator":"User 2","name":"Er","priority":"3","type":"Work"},
{"class":"server.Item","id":3,"assignedTo":"User 1","comments":null,"completed":false,"creator":"User 2","name":"Ga","priority":"1","type":"Work"}]
Now, the user then has the option to edit the task later. On the client side this works fine, but then I need the user to be able to save the new, updated task.
This is my current update function:
def updateList() {
def newItem = Item.findById(request.JSON.id)
newItem.assignedTo = request.JSON.assignedTo
newItem.comments = request.JSON.comments
newItem.completed = request.JSON.completed
newItem.creator = request.JSON.creator
newItem.name = request.JSON.name
newItem.priority = request.JSON.priority
newItem.type = request.JSON.type
newItem.save(flush: true)
render newItem as JSON
}
This doesn't work, however. I get a null pointer exception that says "Cannot set property "assignedTo" on null object. I'm assuming that the findById request is not getting anything for the JSON object, and thus there is no object to assign values to, however I don't know what the problem is considering the items are in fact being put into the Item.list().
This is called with the following JS function on the client side:
$scope.updateList = function() {
angular.forEach($scope.items, function (item) {
// serverList.save({command: 'updateList'}, item);
$http.post('http://localhost:8080/server/todoList/updateList', item)
.success(function(response) {})
.error(function(response) {alert("Failed to update");});
});
};
This might depend on your Grails version, but you should be able to do this:
def update(Item item) {
if (!item) {
// return a 404
} else {
// you should really use a service and not save
// in the controller
itemService.update(item)
respond item
}
}
Grails is smart enough look that item up since there is an ID in the JSON params, and populate the object correctly.
Sort of a work around for anyone else that may need to do this in a basic manner, what I've done that works is clear the list when "Update List" is clicked, then read back in the values that are currently in the client side list.
Grails:
def clearList() {
Item.executeUpdate('delete from Item')
render Item.list()
}
def updateList() {
def newItem = new Item(request.JSON)
newItem.save(flush:true)
render newItem as JSON
}
Javascript:
$scope.updateList = function() { // Update list on the server
serverList.get({command: 'clearList'});
angular.forEach($scope.items, function (item) {
serverList.save({command: 'updateList'}, item);
});
};