Send Finagle stats to Codahale Metrics

Last year I needed to send lots of metrics from some java applications to Graphite, and I did it easily using a library called Metrics.

Recently I had to send some stats from a Finagle based application (Finagle collect and expose some metrics automatically) to the same Graphite server, so I had tried the same approach using the Metrics library, and as a result, I ended up doing a finagle module called finagle-metrics.

So let’s see how to use it! :)

First things first. So, let’s install the finagle-metrics locally. To do that, just run:

git clone https://github.com/rlazoti/finagle-metrics.git
cd finagle-metrics
git checkout tags/version-0.0.1 -b version-0.0.1
sbt publish-local

After that you should see something like this output:

[info]  published finagle-metrics_2.11 to /Users/rodrigolazoti/.ivy2/local/com.github.rlazoti/finagle-metrics_2.11/0.0.1/poms/finagle-metrics_2.11.pom
[info]  published finagle-metrics_2.11 to /Users/rodrigolazoti/.ivy2/local/com.github.rlazoti/finagle-metrics_2.11/0.0.1/jars/finagle-metrics_2.11.jar
[info]  published finagle-metrics_2.11 to /Users/rodrigolazoti/.ivy2/local/com.github.rlazoti/finagle-metrics_2.11/0.0.1/srcs/finagle-metrics_2.11-sources.jar
[info]  published finagle-metrics_2.11 to /Users/rodrigolazoti/.ivy2/local/com.github.rlazoti/finagle-metrics_2.11/0.0.1/docs/finagle-metrics_2.11-javadoc.jar
[info]  published ivy to /Users/rodrigolazoti/.ivy2/local/com.github.rlazoti/finagle-metrics_2.11/0.0.1/ivys/ivy.xml
[success] Total time: 16 s, completed Jan 7, 2015 10:15:30 PM

Okay, the finagle-metris is now installed locally, so from now on we can add it as a dependency to our finagle application. We need to create some folders and files, so let’s do that:

mkdir -p finagle-example/src/main/scala/
cd finagle-example
touch build.sbt
touch src/main/scala/App.scala

Then I’m going to add the following content to build.sbt:

name := "finagle-example"

version := "0.0.1-SNAPSHOT"

scalaVersion := "2.11.4"

libraryDependencies ++= Seq(
  "com.twitter"        %% "twitter-server"  % "1.9.0",
  "com.github.rlazoti" %% "finagle-metrics" % "0.0.1"
)

And finally, let’s create our finagle application. I’m gonna add the following content to /src/main/scala/App.scala:

import com.codahale.metrics.ConsoleReporter
import com.twitter.finagle.{Http, Service}
import com.twitter.finagle.metrics.MetricsStatsReceiver
import com.twitter.io.Charsets
import com.twitter.server.TwitterServer
import com.twitter.util.{Await, Future}
import org.jboss.netty.buffer.ChannelBuffers.copiedBuffer
import org.jboss.netty.handler.codec.http._
import java.util.concurrent.TimeUnit

object App extends TwitterServer {

  val service = new Service[HttpRequest, HttpResponse] {
    def apply(request: HttpRequest) = {
      val response = new DefaultHttpResponse(request.getProtocolVersion, HttpResponseStatus.OK)
      response.setContent(copiedBuffer("hello", Charsets.Utf8))
      Future.value(response)
    }
  }

  val reporter = ConsoleReporter
    .forRegistry(MetricsStatsReceiver.metrics)
    .convertRatesTo(TimeUnit.SECONDS)
    .convertDurationsTo(TimeUnit.MILLISECONDS)
    .build

  def main() {
    val server = Http.serve(":8080", service)
    reporter.start(5, TimeUnit.SECONDS)

    onExit {
      server.close()
    }

    Await.ready(server)
  }

}

Note that I used the ConsoleReporter to report the Codahale’s metrics to the console every five seconds.

Also, note that I didn’t need to do anything related to the finagle-metrics, I just needed to define a location (Reporter) to where the Codahale metrics will be sent, but the metrics themselves were sent automatically (Thanks Finagle for that). :)

To run our example, just execute the following command and wait a few seconds to see the metrics being displayed on the console:

sbt 'run-main App'

Click here to see more about the finagle-metrics library.

Comments »


Map and Reduce Functions in Javascript

Functions like map and reduce are very useful, we can use them to extract values from lists. Nowadays these functions are available in the most recent browsers, but have you ever thought about how to implement them?

So, that’s the idea. Let’s see how to do it in a functional way, in other words, let’s do that using recursion and high order functions. As the post title suggest, the following example will be created in Javascript. :)

At first we’re creating a function called each. We’ll use it to iterate over a list, apply a function and then generate an accumulator. If done it correctly, we will be able to abstract out complex parts of our algorithm, replace it with a function call and keep code condensed and readable.

So let’s see the function:

var each = function(head, tail, acc, fn) {
  if (head != null) acc = fn(acc, head);
  if (tail == null) return acc;

  var _head = tail.length > 0 ? tail[0] : null;
  var _tail = tail.length > 1 ? tail.slice(1, tail.length) : null;
  return each(_head, _tail, acc, fn);
};

Okay, now we can create our map function. Basically a map function is a function that applies a given function to each element of a list and then returning another list of results.

It’s our map function:

var map = function(list, transformFn) {
  return each(null, list, [], function(acc, head) {
    acc[acc.length] = transformFn(head);
    return acc;
  });
};

See, it’s not a big deal. We use the each function to iterate over the list and replace each list value by the result of transform function. So how can we use it? Let’s transform (multiply each value by 2) a simple array of numbers.

var array = [1, 2, 3, 4, 5];
var multiplyFn = function(n) {
  return n * 2;
};

console.log(map(array, multiplyFn));
//[2, 4, 6, 8, 10]

And now the last one function called reduce. Different from map function, this one returns only one value with an initial value predefined that is the result of a combine function executed recursively over each element of the list. See the following function:

var reduce = function(list, initalValue, combineFn) {
  return each(null, list, initalValue, function(acc, head) {
    return combineFn(acc, head);
  });
};

As an usage example, let’s think up a shopping cart with some items. We’ll need to calculate the total order to show it up at the checkout page.

var Item = function(_description, _price) {
  this.description = function() { return _description; };
  this.price = function() { return _price; };
};

var shoppingCart = [
  new Item("iPhone 6", 749.00),
  new Item("The Amazing Spider-Man Hero FX Glove", 14.24),
  new Item("Playstation 4", 399.00)
];

var sumFn = function(total, item) {
  return total + item.price();
};

console.log(reduce(shoppingCart, 0, sumFn));
//1162.24

As can be seen, functions like map and reduce are great to transform and/or combine lists, and functional programming is good to abstract out complex algorithms.

Comments »


Measuring Execution Time in JavaScript

Sometimes we need to know if our code is fast enough for a production environment, for example let’s take a simple javascript function like that:

var generateMessageA = function(name, username, email) {
  return "<h1>Hello " + name + "</h1>" +
         "<p>Thank you for your registration.</p>" +
         "<p>Your username is: " + username + "</p>" +
         "<p>Your email is: " + email + "</p>";
};

It’s a very simple function, isn’t it? :)

But you in an inspired day, decide to create a way to abstract the code above to something like a template method, thus you could use that at other functions. Let’s see our new function:

var interpolate = function(template, data) {
  var result = template;

  for (var property in data)
    result = result.replace(
      new RegExp('#{' + property + '}', 'g'),
      data[property]
  );

  return result;
};

var generateMessageB = function(name, username, email) {
  return interpolate(
           "<h1>Hello #{name}</h1>" +
           "<p>Thank you for your registration.</p>" +
       "<p>Your username is: #{username}</p>" +
       "<p>Your email is: #{email}</p>",
       { name:name, username:username, email:email }
     );
};

Now we have our cool template function, but let’s wonder ourselves if we could have some performance issues adding that new function. What do you think about it?

Yeah, probably you’re thinking about a way to measure our new function against the first one, and that’s exactly what we’re going to do.

To do that, we can use these two functions console.time() and console.timeEnd() to measure the time taken by a function execution. The function console.time() takes a timer name, and console.timeEnd() must take the same timer name, then it’ll report on the execution time since the timer started. Let’s use them to measure our two functions:

var iterations = 1000000;

console.time('generateMessageA');
for (var i=1; i<=iterations; i++)
  generateMessageA("Jon Snow", "jsnow", "jsnow@starkhouse.com");
console.timeEnd('generateMessageA');

console.time('generateMessageB');
for (var i=1; i<=iterations; i++)
  generateMessageB("Jon Snow", "jsnow", "jsnow@starkhouse.com");
console.timeEnd('generateMessageB');

And the output is:

generateMessageA: 1285.380ms
generateMessageB: 8583.070ms

Wow, the second function is about 7 times slower than the first one, and it would probably be a problem in a real application.

Comments »


Lançamento do meu livro "Armazenando dados com Redis"

O livro Armazenando dados com Redis que escrevi recentemente foi publicado pela editora Casa do Código em formato impresso e digital no dia 12/05.

Escrever um livro técnico foi um grande desafio pois eu já tinha publicado artigos técnicos mas nunca algo na dimensão de um livro, e imagino que por isso eu achei fantástico escrevê-lo. Também fiquei muito feliz com o resultado final do livro e espero que gostem do livro.

Sobre o livro

Saber usar a melhor ferramenta para cada problema é determinante para qualquer pessoa ligada à área de tecnologia e atualmente com o desenvolvimento de novos bancos de dados, as opções para essa área aumentaram bastante, trazendo muito mais poder às aplicações.

Nesse livro, Rodrigo Lazoti vai te mostrar porque trabalhar com o Redis e bancos de dados chave/valor podem trazer enormes ganhos de performance para sua aplicação, além de ser a ferramenta ideal para diversos sistemas.

Você vai aprender a trabalhar com estruturas clássicas e modernas de dados e armazenamento, filas, listas, conjuntos, além da configurações de mecanismos de publish e subscribe e claro, como usar todo o poder da API do Redis.

Sobre a editora

Trabalhar com o pessoal da editora Casa do Código foi uma ótima escolha na minha opinião, pois o pessoal te oferece todo o apoio e ajuda necessária durante o processo de escrita do livro. Além do fato de ser uma editora amplamente conhecida e reconhecida pelos desenvolvedores e pessoas ligadas a área desenvolvimento de software em todo o Brasil.

Como adquirir o livro

Basta acessa o link:

http://www.casadocodigo.com.br/products/livro-redis

Comments »


How I use Emacs

Getting started with an editor like Vi or Emacs isn’t too easy in the beginning, so I’m going to show you what packages I’m currently using to write code in Javascript, Ruby and a little bit in Scala.

My emacs configuration is very simple and it was based on Emacs Prelude. My setup can be found in my repo at https://github.com/rlazoti/emacs.d and you also can see there a list with my useful shortcuts that I use constantly.

If you wish to install it, just type:

1
git clone https://github.com/rlazoti/emacs.d.git ~/.emacs.d

Installation

There are many ways to install Emacs, you could install it from the sources or maybe using a package manager. I’m going to show the way that worked better for me. ;) Let’s see it…

I installed on the Mac OS a ‘mac port’ of emacs 24. I did it with Homebrew but it’s possible to download a version directly of here. To install with Homebrew do:

1
brew tap railwaycat/emacsmacport

And then

1
brew install emacs-mac

That’s it! It should be ready to use.

Repositories

Emacs 24 included a package manager called package.el and it already include a repository called ELPA, but it’s possible to use multiple repositories. In fact I use just one more repository called MELPA.

Packages

These are the main packages I use:

Comments »