lundi 29 juin 2020

Lambda function to parse logs from aws log groups and log streams in cloudwatch and trigger an AWS SNS Notification

I have a setup to push all my rails application logs to cloud watch log groups,Now I need to run a lambda function daily at the end of the day to parse all the logs from cloudwatch log groups and count number of 500 error codes in that day and has to trigger an SNS notification.

currently I have a setup, I created the metric filter on log groups to filter the logs based on a keyword, whenever the metric filter finds the keyword , it will raise an alarm and triggers an lambda function, this lambda function takes the timezone of that keyword and collects logs 5 seconds before and 5 seconds after and triggers an another sns notification to send an email.

Below is the NodeJs code which will perform the above mentioned activity.

var aws = require('aws-sdk');
var cwl = new aws.CloudWatchLogs();
var sns = new aws.SNS();

exports.handler = function(event, context) {
    console.log(event);
var message = JSON.parse(event.Records[0].Sns.Message);
var requestParams = {
    metricName: message.Trigger.MetricName,
    metricNamespace: message.Trigger.Namespace
  };
  cwl.describeMetricFilters(requestParams, function(err, data) {
    if(err) console.log('Error is:', err);
    else {
        console.log('Metric Filter data is:', data);
        getLogsAndSendEmail(message, data);
     }
   });
 };

function getLogsAndSendEmail(message, metricFilterData) {
var metricFilter = metricFilterData.metricFilters[0];
let runningCount=4;
var params = {
  logGroupName: metricFilter.logGroupName,
  descending: true,
  limit: runningCount,
  orderBy: 'LastEventTime'
};

cwl.describeLogStreams(params, function(err, data) {
  if (err) console.log(err, err.stack); // an error occurred
  else{
      let logStreams=new Array();
      for ( var i = 0; i < runningCount; i++ ) {
          logStreams[i]= data.logStreams[i].logStreamName;
      }
        var parameters = {
            'logGroupName' : metricFilter.logGroupName,
            'logStreamNames': logStreams,
            'filterPattern' : metricFilter.filterPattern ? metricFilter.filterPattern : '"Internal error"', 
            'startTime' : (new Date()).getTime()-60*1000
        };
        cwl.filterLogEvents(parameters, function (err, data){
            if (err) {
                console.log('Filtering failure:', err);
            } else {
                console.log(data.events.length)
                console.log('above is data.events.length')
                for (var i = 0; i < data.events.length; i++) {
                    getDetailedLog(data.events[i],metricFilter.logGroupName);
                }
                console.log('Exiting Describe Logs ');
                
            }
        });
  }     
});

}

function getDetailedLog(item,logGroupName){
console.log('Entering Detailed Logs ');
var timestamp=item.timestamp;
var parameters2 = {
    'logGroupName' : logGroupName,
    'logStreamNames': [item.logStreamName],
    'startTime' : timestamp - 5000,
    'endTime' : timestamp + 5000,
};
cwl.filterLogEvents(parameters2, function (err, data){
    if (err) {
        console.log('Filtering failure:', err);
    } else {
        console.log("===SENDING TO SNS===");
        let errorLogs=data.events.map(x => x.message);
        sendToSNS(errorLogs,logGroupName);
        
    }
});

}

function sendToSNS(data,logGroupName){
var logData = 'LogGroupName : '+logGroupName+'\n\nError Logs: \n\n';
for ( var i=0;i<data.length;i++ ) {
    logData += ( data[i] + '\n\n');
}
var snsEmailArn='arn:aws:sns:ap-southeast-1:test-logs-topic';
var params = {
  Message: logData,
  Subject: 'error LOGS',
  TopicArn: snsEmailArn
};
sns.publish(params, function(err, data) {
  if (err) {
      console.log(err, err.stack); // an error occurred
  }
  else {
      console.log("SNS email success: ");  // successful response
  }
});

}

Now my requirement is to parse the logs and count number of 500 internal server errors that are logged in this cloudwatch log group in a day and triggers a notification to send an email regarding this information on daily basis.

please help me in editing this code and in meeting my requirement.

jeudi 25 juin 2020

Gravatar shows hash instead of picture

i want to use gravatar to show pictures on my platform, but instead of doing so i only see the MD5 hash.

Here is my code of "application_helper.rb"

def avatar_url(user)
    gravatar_id = Digest::MD5::hexdigest(user.email).downcase
    "https//www.gravatar.com/avatar/#{gravatar_id}.jpg?d=identical&s=150"
  end
end

I also tried d=mmand d=identicon, which also did not work.

Here is the code im using in the navbar:

<a href="#" class="dropdown-toggle" data-toggle="dropdown"
                  role="button" aria-haspopup="true" aria-expanded="false">
                  <%= image_tag avatar_url(current_user), class: "img-circle" %>&nbsp;
                  <%= current_user.fullname %> <span class="caret"></span>
</a>

Picture of the navbar

Anything i could try?

Thank you for your help :)

mercredi 17 juin 2020

How to check if today is monday?

To know the Year, I use <%= Time.now.year %>

So I can check the year using <% if Time.now.year == 2020 %>You are living the 2020!<% end %>

But... how to check if today is monday? or sunday?

lundi 15 juin 2020

Locate element in multi level array using Groovy

How can I find the userGroupId from a user group type=xyz and userGroupId=5645 from below json using Ruby ?

[
    {
        "userId": "00u2ob4m5",
        "userGroups": [
            {
                "userGroupId": "5645",
                "userGroupType": "abc"
            }
        ]
    },
    {
        "userId": "0e72828b-6417-4371-9588-4cbb55db7e32",
        "userGroups": [
            {
                "userGroupId": "5645",
                "userGroupType": "xyz"
            }
        ]
    },
    {
        "userId": "10592b48-53bf-400e-a417-0079081d1ee0",
        "userGroups": [
            {
                "userGroupId": "7568",
                "userGroupType": "xyz"
            }
        ]
    }
]

samedi 13 juin 2020

how to pass data between views/pages in Ruby on rails?

I have a ruby on rails app. I have a view that lists hyperlinks as such, this view is also rendered via same controller/action . when user clicks hyperlinks displayed on this page they go to the same controller/action, with a different id parameter. I want to be able to tell in my controller/view how user gets to these pages, i.e. whether user clicked on one of these hyperlinks vs user came through a different source?

<div id='list'>
  <a href='controller/action/1'> some link 1 </a>
  <a href='controller/action/2'> some link 2 </a>
</div>

vendredi 12 juin 2020

Disable and enable Select Value using Java Script

I am using below code.If i click Testing 1 or Testing 2 or selectAll,new rows will be created.I need to disable DatatType and Expected set value column if Execution Type is Get.If I select Set from Execution Type, DataType and Expected set value column should be enabled.How to implmente this? I am using this code in Html.erb file.How to create separate js method?

https://jsfiddle.net/bx5fa2vu/

$("#all").on("click", function() {
  if ($(this).is(":checked")) {
    let boxes = $("#paramTable input[type='checkbox']").not(this).not(":checked");
    boxes.each(function() {
      $(this).click();
    });
  } else {
    let boxes = $("#paramTable input[type='checkbox']:checked").not(this);
    boxes.each(function() {
      $(this).click();
    });
  }
});



$("#paramTable input[type='checkbox']:not(#all)").on("click", function() {
  if ($(this).is(":checked")) {
    let name = $(this).parent("td").next("td").next("td").text().trim();
    let newname = name.split('.').join('');
    let newrow = $("<tr>");
    let newcell = $("<td> ");
    let newSel=$("<select class='ExeType' name='ExeTypeValue'><option value='getData'>Get</option><option value='SetData'>Set</option></select>")
    newcell.append(newSel);
        newrow.append(newSel);
    let newcell1 = $("<td> ");

    let newinput = $("<input type='text' class='parameterName' name='" + newname + "' id='" + newname + "' value='" + name + "'/>");
    newcell1.append(newinput);

    newrow.append(newcell1);
 let newcells = $("<td><select class='parameterDscription' name='parameter_description'><option value=''>Select Data Type</option><option value='OCTET_STRING'>String</option><option value='INTEGER'>Integer</option><option value='INTEGER32'>Unsigned Integer</option><option value='IPADDRESS'>IP Address</option><option value='x'>Hex String</option></select></td><td><input type='text' class='expectedValue' name='expected_value'></td>");
     newrow.append(newcells);
    $("tbody.parameter_table").append(newrow);
  } else {
    let name = $(this).parent("td").next("td").next("td").text();
    let newname = name.split('.').join('');
    console.log("newname: " + newname)
    $("#addParamTable").find("#" + newname).closest("tr").remove();
    $("#all").prop("checked", false);
  }
})

How to sort an array based on enum hash and return the maximum in Ruby?

enum custom: {
   AB1:  1,
   AB45: 10,
   XY:   15
}

Input:

array = [AB45, XY]

Output should be: XY as XY is maximum based on the value's value (I mean value of key XY is highest).

I tried the following: MyClassName.customs.values_at(*array) . This returns [10,15]

jeudi 11 juin 2020

How to sum the values of an associated table with multiple joins without duplicates

I have a Rails 3 app, using mysql, with 3 models: Order, Payment, Refund. Payment and Refund both have a belongs_to association with Order. Order has_many payments and refunds respectively.

I am simply trying to get totals for the payments and refunds, for the orders within a given time range, broken down by day.

The closest I have been able to come is with the following code:

    scope = Order.in_a_completed_status.purchased_between(from, to)

    scope = scope.joins(<<-SQL.strip_heredoc)
      INNER JOIN payments ON payments.order_id = orders.id AND payments.status <> "Removed"
    SQL

    scope = scope.joins(<<-SQL.strip_heredoc)
      LEFT JOIN refunds ON refunds.order_id = orders.id
    SQL

    scope = scope.select(<<-SQL.strip_heredoc)
      COALESCE(sum(payments.amount), 0) as value,
      COALESCE(sum(refunds.amount), 0) as total_refund,
      DATE(CONVERT_TZ(orders.created_on, '+00:00', '#{Time.current.formatted_offset}')) AS date
    SQL

    scope = scope.group("date")

The problem with the above is that it will add a refund amount multiple times if there are multiple payments for the order. So if we have the following tables

Orders
____________________________
| id | created_on          |
| 34 | June 4th, 2020      |
____________________________

Payments
______________________________________
| id | order_id | amount | status   |
| 2  |   34     | 500    | complete |
| 3  |   34     | 200    | complete |
______________________________________

Refunds
___________________________
| id | order_id | amount  |
| 6  |   34     | 300     |
|____|__________|_________|

The total_refund that results for June 4th will be 600 instead of 300 because the refund gets added once for each payment, instead of just once. I have tried adding in a DISTINCT clause and various other things but I haven't gotten anything to work. Any help or insights would be greatly appreciated. Thanks in advance.

how to set or avoid multiple Set-Cookie response?

When I

$ curl --head https://myawesomeweb.app/login

As a response I've got a:

HTTP/1.1 200 OK
Date: Fri, 12 Jun 2020 02:28:06 GMT
Server: Apache
ETag: "S0meEnc0d3dS7r1n9"
Cache-Control: max-age=0, private, must-revalidate
X-UA-Compatible: IE=Edge,chrome=1
X-Runtime: 0.013907
Set-Cookie: _session_id=S0meEnc0d3dS7r1n9; path=/; HttpOnly
Status: 200
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Set-Cookie: HttpOnly;Secure
Content-Type: text/html; charset=utf-8
Set-Cookie: SERVERID=; Expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/
Cache-control: private

The last Set-Cookie makes me confused, because of the expired date. My /etc/httpd/conf.d/security.conf's content is as follow:

Header set X-Frame-Options SAMEORIGIN
Header set X-XSS-Protection "1; mode=block"
Header set X-Content-Type-Options nosniff
Header set Set-Cookie "HttpOnly;Secure"

After searching for a while I know from here that there can be multiple "Set-Cookie" and from here I know that sometimes it is ok to have Set-Cookie with expired 01-Jan-1970 00:00:01 DateTime. The question is where can I config Set-Cookies to avoid the last one or set it with a proper expiring date.

mercredi 10 juin 2020

Rails-undefined method `id' for nil:NilClass

I am getting error undefined method `id' for nil:NilClass. I need to find id of oidValue.if id is nil for oidValue and i need to search oid2 table for get oidValue.How to check nil here.Below code is i am using.Not working if oidId is nil.

   oidId = Oid1.find_by(oid: oidvalue).id.to_s
    if oidId.nil?
      oidId = Oid2.find_by(oid: oidvalue).id.to_s
    end

mardi 9 juin 2020

Unpermitted nested params rails

I'm having problems sending data to my database through the client_controller, the client model has the has_many relationship with client_address, when trying to submit the data, the following fields are registered (client, personal_documents and client_bank_information), but the client_addresses is not saved to the bank on the rails console apacere it was not allowed (Unpermitted parameter:: client_address_attributes), thanks for the help!

model:

class Client < ApplicationRecord
    has_one :client_bank_information, :dependent => :destroy
    has_one :personal_document, dependent: :destroy
    has_many :client_addresses, :dependent => :destroy

    accepts_nested_attributes_for :client_bank_information, allow_destroy: true
    accepts_nested_attributes_for :personal_document, allow_destroy: true
    accepts_nested_attributes_for :client_addresses, allow_destroy: true
end

controller:

class ClientsController < ApplicationController
  include ErrorSerializer

  # POST /clients
  def create
    @client = Client.new(client_params)
    if @client.save
      render json: @client, status: :created, location: @client
    else
      render json: ErrorSerializer.serialize(@client.errors)
    end
  end

private

  def client_params
    params.permit(
                                   :name, 
                                   :email, 
                                   :phone, 
                                   :cpf_cnpj, 
                                   :accept, 
                                   :version_term_accept, 
                                   :birth_date,
                                   personal_document_attributes: [:rg_front,
                                                                  :rg_verse,
                                                                  :cpf,
                                                                  :cnh_front,
                                                                  :cnh_verse,
                                                                  :bank_card_front,
                                                                  :proof_residence,
                                                                  :profile_photo
                                                                 ],
                                   client_bank_information_attributes: [:bank, 
                                                                        :account_type, 
                                                                        :agency, 
                                                                        :account_number
                                                                       ],
                                   client_address_attributes: [  
                                                                 :spot_to_clean, 
                                                                 :zip_code, 
                                                                 :street, 
                                                                 :street_number, 
                                                                 :complement, 
                                                                 :district, 
                                                                 :city, 
                                                                 :state
                                                                ]
    )
  end

end

bundler: failed to load command: rake

I'm trying to install a rails 3.2.22, ruby 1.9.3 app locally. I'm using bundler 1.17.3. I've managed to get through an openssl error, and a mysql 1.9.2 error, but now I'm getting:

bundler: failed to load command: rake (/Users/{username}/.rvm/gems/ruby-1.9.3-p551/bin/rake
NoMethodError: undefined method `b' for "db:schema:load":String

I've been searching for quite some time, but I haven't hit on any results on how to fix this issue. Anyone have any ideas? Thanks.

dimanche 7 juin 2020

Rails-A JSON text must at least contain two octets Error

I am getting error "A JSON text must at least contain two octets!" while performing api execution.For Success 200 response code i am getting proper json format.But 404 error i am getting below response which is empty string.Can anyone help how to handle this error?.

Response

"404"
""
"RESPONSE_TIME = 1.96193"
"Encoding = UTF-8"
""
Threw an exception inside create Controller.getparameter() A JSON text must at least contain two octets!

Rails Controller code

 if OpetationType == "Get"
            client = Client.new
            response = client.get_call(macaddress, parameter)
            redis_client = Redis.new
            access_token = redis_client["Token"]
            response_time = client.response_time
            p "RESPONSE_TIME = #{response_time}"
            p "Encoding = #{response.body.encoding}"
            response.body.force_encoding("ISO-8859-1").encode("UTF-8")
            p response.body
            result_hash["response"].push({"macaddress": macaddress, "body": 
            JSON.parse(response.body), "response_time": response_time.to_s})
            result_hash["status"].push("#{response.code}")

end

mardi 2 juin 2020

Rails-How to display data from database into textfields and update and delete it

My requirement is to display data from databse in textfields.I have drop-down with values View and Modify.If i click modify from dropdown,It will create textfields in inside table along with checkboxes.User can edit and delete the records by selecting checkboxes.Please help how to bring this changes.I am new to rails.

TIA

lundi 1 juin 2020

pop record from ActiveRecord without deleting in database Rails 5.2

In rails 3.2 pop helps in removing the record from ActiveRecord.

rec = User.find(1).histories
rec.pop => remove last history and output class will be in ActiveRecord 

In Rails 5.2, same pop is not working.

Looking for same ActiveRecord class as output.

Also, the record should not be removed in the database.