Docker – Post Install – O que fazer depois de instalar?

Olá,

Recentemente tive alguns problemas com o Docker relacionados não com ele, mas com os logs gerados por ele e o espaço em disco disponível que eu tinha em uma instância na AWS.

Após muito varrer o disco em busca dos dados que mais ocupavam espaço, vi que os logs estavam crescendo exponencialmente e decidi usar o logrotate, um utilitário pro Linux para rotacionar os logs quando estes atingem as regras que você define em um arquivo de configuração.

Para instalar o logrotate, execute:

sudo apt-get update
sudo apt-get install logrotate

Após instalar execute “logrotate” para saber se está instalado corretamente.

Após instalar, precisamos configurar uma regra no logrotate para os logs do Docker. Então execute:

nano /etc/logrotate.d/docker-container

Obs: Eu usei o “nano”, mas você pode usar o “vi” ou “vim” se preferir. Dentro do editor, cole a seguinte regra para o logrotate:

/var/lib/docker/containers/*/*.log {
  rotate 7
  daily
  compress
  size=1M
  missingok
  delaycompress
  copytruncate
}

Salve o arquivo, feche o editor e pronto, logrotate configurado.

No meu caso, eu deixei os arquivos de log com no máximo 1M de tamanho, mas você poderá aumentar para quanto quiser.

Caso você queria testar o logrotate e ver o que ele vai fazer, execute o comando:

logrotate -df /etc/logrotate.d/docker-container

 

Obs: Além disso, mesmo configurando, havia um arquivo que parece ter corrompido e depois de muito pesquisar eu acabei tendo que apagar este arquivo, pois estava impedindo o logrotate de executar, já que ele parece usar este arquivo como referência para alguma coisa. Então, caso aconteça contigo, apague o arquivo “status” na pasta do logrotate com o comando:

rm /var/lib/logrotate/status

 

Bom, é isso pessoal. Espero que isso ajude a economizar espaço com os logs gerados pelo Docker. É claro que isto não se aplica só ao Docker, você pode criar regras para qualquer arquivo, basta especificar o pattern para os arquivos e colocar as regras.

Ah, e no meu caso o espaço utilizado foi de 76% para 34% do disco, ou seja, 42% do disco era log do Docker.

Obrigado e até o próximo post pessoal.

SentryCar – Sistema de rastreamento e bloqueio veicular

Olá,

Recentemente desenvolvi todo um sistema de rastreamento e bloqueio de veículos, chamado de SentryCar.

O projeto consiste em uma aplicação mobile ou web que pode ser acessada por um cliente/usuário para rastrear um ou vários veículos, monitorar sua localização e velocidade, além de bloquear e desbloquear o carro, cortando a fonte de combustível quando ele atinge 20Km/H ou menos.

O sistema é dividido em 6 partes:

  • Apps (iOS e Android).
  • Web (mesmo sistema acessado pelos apps e pagamento da mensalidade).
  • Servidor (servidor desenvolvido em Go para receber conexões TCP/IP dos rastreadores e coletar os dados necessários).
  • Banco de dados MySql.
  • Rastreadores importados do AliExpress e interpretação do protocolo definido pelo fabricante.
  • API que permite qualquer device via HTTP/TCP enviar sua posição, desde que esteja cadastrado no sistema. Tanto os aplicativos, como o sistema web e o rastreador, utilizam a mesma API.

 

Eu precisei fazer uns vídeos para que a Apple aprovasse meu app, então fiz alguns vídeos demos e coloquei em minha conta do Youtube:

  • https://www.youtube.com/watch?v=pKCQLeSOvdg
  • https://www.youtube.com/watch?v=0RsqSgQETRc

 

URL para demonstração:

  • http://sentrycar.prsolucoes.com

 

Caso alguém precise desenvolver algo do tipo, podemos fazer uma parceria.

 

Obrigado e até o próximo post pessoal.

Limpando os dados do Docker em sua máquina (containers e imagens)

Olá,

Quem utiliza Docker no dia-a-dia sabe que ele deixa muitos lixos na máquina em que está rodando, principalmente se você fica criando containers de teste como eu.

Quando você sai do container o Docker não apaga eles automaticamente, o que vai enchendo o disco e você acaba recebendo o erro: No space left on device.

Como eu passo por isso sempre, resolvi fazer uma sequência de comandos para copiar e colar no terminal, a fim de que o ambiente fique limpo denovo.

docker rm -v $(docker ps -a -q -f status=exited)
docker rmi $(docker images -f "dangling=true" -q)
docker volume rm $(docker volume ls -qf dangling=true)

 

Espero ter ajudado com este artigo.

Obrigado e até o próximo post pessoal.

 

Usando o auto-update do Fastlane

Olá pessoal,

Recentemente tivemos um necessidade de fazer com que o Fastlane (ferramenta para deploy contínuo – http://fastlane.io/) fizesse a atualização de suas dependências automaticamente, isso inclui todos esses caras:

cert, credentials_manager, deliver, fastlane, fastlane_core, frameit, gym, match, pem, pilot, produce, scan, screengrab, sigh, snapshot, spaceship, supply

Toda vez que vamos usar o Fastlane para subir as aplicações tem atualizações novas de suas dependências e que muitas das vezes gera algum erro no envio e não conseguimos subir os aplicativos até que atualizemos manualmente as dependências necessárias com o comando “gem update …” e depois começamos o processo novamente de deploy.

Isso é bem chato, então a primeira coisa que pensei foi em adicionar o “gem update” em nossa ferramenta de integração contínua, GoCI (http://github.com/prsolucoes/goci), antes de fazer as chamadas ao Fastlane.

A segunda opção era buscar na documentação para saber se existe alguma coisa pronta para este problema, e foi ai que achei o comando “update_fastlane”. Após olhar a documentação e realizar alguns testes, resolvi escrever o passo-a-passo para implementar isso. Vamos à prática:

  1. Adicione no início do seu arquivo Fastfile, antes de qualquer coisa, esta linha:

    update_fastlane

  2. Adicione as seguintes linhas ao seu arquivo “.bash_profile” ou “.bashrc”, que fica na pasta do seu usuário, ex (nano ~/.bash_profile):

    export GEM_HOME=~/.gems
    export GEM_SPEC_CACHE=$GEM_HOME/specs
    export PATH=$PATH:~/.gems/bin

  3. Execute o arquivo modificado com o comando “source”, ex:

    source ~/.bash_profile

  4. Atualize o rubygems e o gem:

    gem install rubygems-update
    sudo gem update –system

  5. Instale suas gems novamente, as que você usa. No meu caso era o fastlane e cocoapods, então fiz assim:

    gem install cocoapods fastlane –no-ri –no-rdoc

Com tudo isso feito, você já preparou o seu ambiente e atualizou tudo o que é necessário para que o auto-update do fastlane funcione. Agora basta você executar suas tarefas do fastlane que ele vai executar o auto-update antes de tudo.

Obs: Nós definimos uma novo diretório para as “gems” do ruby porque sem isso o fastlane irá reclamar que a pasta de “gems” é do usuário root (sendo necessário fazer um sudo + comand) e não sua.

 

Espero ter ajudado com este artigo.

Obrigado e até o próximo post pessoal.

Instalando drivers não assinados (unsigned) no Mac/OSX

Olá,

Recentemente precisamos instalar o driver de um adaptador de Rede Ethernet RJ45 no Mac (Plugable USB 3.0 to 10/100/1000 Gigabit Ethernet LAN Network Adapte – Chiptset LAN7500) e o adaptador não ligava e não funcionava de jeito algum.

Porém ao tentar carregar o driver via terminal aparecia a mensagem:

/System/Library/Extensions/LAN7500.kext failed to load – (libkern/kext) not loadable (reason unspecified); check the system/kernel logs for errors or try kextutil(8).

O problema está na verdade não com o driver, mas com o sistema que é o Sierra. Parece que depois de alguma versão El Captain ou Yosemite a Apple passou a aplicar um sistema de segurança nos drivers que só pode ser desabilitado em modo de recuperação.

Então para fazer o driver funcionar e verificar se você possui o mesmo problema, faça o seguinte:

sudo kextload /System/Library/Extensions/LAN7500.kext

Substitua “LAN7500.kext” pelo nome do seu driver. Se ao executar você receber a mensagem abaixo, então você está com o mesmo problema:

/System/Library/Extensions/LAN7500.kext failed to load – (libkern/kext) not loadable (reason unspecified); check the system/kernel logs for errors or try kextutil(8).

Agora reinicie seu Mac segurando as teclas CMD + R. O sistema iniciará em modo de recuperação. Acesse o menu “Utilitários > Terminal” e digite:

csrutil disable

Ele vai informar que você precisa reiniciar, então digite agora:

reboot

Ao reiniciar seu Mac, o driver já será carregado e tudo funcionará.

 

Adaptador rede Mac OSX

 

Espero ter ajudado com este artigo.

Obrigado e até o próximo post pessoal.

Golang – GoDiffExporter – Exporte seus DIFFs com este utilitário

Olá,

Recentemente precisei compartilhar o resultado de um DIFF (git diff) para uma outra pessoa fazer a conferência e com isso eu precisava passar o acesso ao bitbucket e o link do commit específico para a conferência.

Isso me gerava um certo trabalho que eu não gostaria de ter toda vez que precisasse fazer isso, foi ai que pensei então no GoDiffExporter, um exportador em PDF de um arquivo DIFF qualquer.

Basicamente o parser do DIFF é feito e depois eu itero nas diferenças e crio o PDF, usando a lib GoFPDF, que inclusive colaborei recentemente adicionando o suporte a fontes embarcadas através de um array de bytes que vai dentro da sua própria aplicação, removendo a necessidade de distribuir as fontes em si (https://github.com/jung-kurt/gofpdf/pull/79).

O resultado do GoDiffExplorer é um PDF como este:

 

O projeto e as instruções de como instalar e usar estão na página do projeto:

https://github.com/prsolucoes/godiffexporter

 

Espero ter ajudado com este artigo.

Obrigado e até o próximo post pessoal.

Android – Debug de aplicação via WiFi usando ADB sem precisar de root

Olá,

Recentemente tive a necessidade de rodar a aplicação pelo Android Studio sem usar cabo, por questões de comodidade mesmo, e após pesquisar e fazer vários testes, preparei um tutorial sem simples.

  1. Desconectar o seu dispositivo do computador, caso esteja.
  2. Conectar o seu computador de desenvolvimento e o seu dispositivo Android na mesma rede WiFi.
  3. Habilitar o modo desenvolvedor em seu dispositivo (Configurações > Sobre > Apertar 7 vezes em Número da versão).
  4. Habilitar a depuração USB (Configurações > Programador > Depuração USB).
  5. Obtenha o IP do seu dispositivo em Configurações > Sobre > Status > Endereço IP.
  6. Abrir o terminal e executar (troque o IP abaixo pelo IP do seu dispositivo):
    adb tcpip 5555
    adb connect 192.168.0.103:5555
  7. Rodar a aplicação no Android Studio normalmente e se tudo deu certo seu dispositivo aparecerá na lista de devices como se estivesse conectado via cabo.

 

Espero ter ajudado com este artigo.

Obrigado e até o próximo post pessoal.

Mobile – Como as redes de anúncios (Ad Networks) realizam o tracking de campanhas

Olá pessoal,

Uma dúvida muito comum e também uma informação muito importante, é saber como fazer o tracking (ou rastreamento) de um usuário que fez o download e instalou um determinado aplicativo através de um link, banner ou uma campanha em geral.

É importante entender que não existe um jeito fácil, simples e universal para que isso aconteça e pode ser que alguma informação se perca no meio do caminho dependendo das ações dos usuários. Cada plataforma resolveu este problema de um jeito diferente.

No caso da Apple funciona assim:

Um usuário utiliza uma ferramenta de anúncios que irá exibir um banner, link ou algo do tipo no dispositivo do usuário. O link contido neste banner é um link que contém uma informação especial chamada pela Apple de IDFA, que consiste em um token específico para anúncios e é único por device. A Apple não permite o uso desse token outro fim além de usá-lo para tracking de anúncios e qualquer tentativa fora esta terá o app rejeitado, como está em sua documentação (Link 1, Link 2, Link 3).

Vou usar o exemplo do Google Analytics para explicar como ele consegue através do IDFA fazer o tracking de suas campanhas.

Um anúncio exibido pelo Google em suas redes de anúncio teria um link com uma estrutura parecida com esta:

http://click.google-analytics.com/redirect?
tid=UA-1234-1 // Google Analytics Tracking ID.
&idfa=BBA44F63-E469-42BA-833A-2AC550310CB3 // Identifier for Advertising (IDFA)
&aid=com.bundle.myapp // App ID.
&cs=network // Campaign source.
&cm=cpc // Campaign medium.
&cn=campaign_name // Campaign name.
&url=https%3A//itunes.apple.com/us/app/myApp/id123%3Fmt%3D8 // Redirect URL to iTunes.

Esse link do anúncio do Google vai registrar no servidor deles que você clicou nele e vai gravar as informações que ele deseja para depois juntar as peças e cruzar as informações. Após gravar o que ele precisa, ele vai redirecionar você para a loja da Apple, indo direto para o aplicativo desejado quando você clicou no anúncio.

Quando você instalar o aplicativo desejado, o SDK do Google contido dentro do seu aplicativo vai obter o IDFA do seu aparelho e enviar para o servidor deles. Seria algo assim:

Ah, então você é o IDFA “ABC123456” que clicou na campanha “C123”, estou adicionando +1 no contador de instalação, bem como todas as informações do seu dispositivo. Obrigado.

Na documentação do Google, tem mais detalhes, mas a regra é esta.

https://developers.google.com/analytics/solutions/ios-install-tracking#redirect 

Segue uma imagem que o Google fez para exemplificar seu fluxo:

ios-install-tracking-redirect

A segunda solução do Google Analytics é fazer com que a rede de anúncios envie assincronamente um “ping” para a URL:

click.google-analytics.com/ping?param1=value1&param2=value2

E com isso poderá ser feita a contabilidade também server-side posteriormente pelas ferramentas.

 

No caso do Google funciona assim:

O Google criou uma classe que atua como um Broadcast Receiver, que receberá estes dados assincronamente quando um usuário instalar o aplicativo através de uma campanha.

Basicamente o Google Play vai fazer um broadcast com a informação somente quando o aplicativo for instalado pela loja e os dados da campanha estiverem disponíveis, ou seja, se ele veio com os parâmetros de campanha definidos quando ocorreu a instalação.

Estes dados serão consumidos pelo seu broadcast que irá submeter os dados para sua plataforma de anúncios. Se você usa o SDK do Google Analytics e definiu que ele será o “recebedor” destas informações, ele será o responsável por jogar estas informações de campanha para o servidor do Google, ou então você captura e repassa isso para diversas ferramentas manualmente, pois uma limitação do Android é que só pode existir um Broadcast Receiver para Install Referrer.

O AppsFlyer fez um Broadcast Receiver especial que consegue receber estes dados e depois repassar para todos os outros Broadcast Receivers que você tiver, automaticamente (Link de como usar), permitindo então você possuir diversos Broadcast Receivers.

Documentação:

https://developers.google.com/android/reference/com/google/android/gms/tagmanager/InstallReferrerReceiver

https://developers.google.com/android/reference/com/google/android/gms/analytics/CampaignTrackingReceiver

 

Basicamente o link no padrão para o Google Play seria assim:

https://play.google.com/store/apps/details?id=com.example.application&referrer=utm_source%3Dgoogle%26utm_medium%3Dcpc%26utm_term%3Drunning%252Bshoes%26utm_content%3Dlogolink%26utm_campaign%3Dspring_sale

É importante entender que a informação que você terá é o texto dentro do parâmetro “referrer”, que deverá estar no padrão URL Encoded, ou seja, sem os símbolos “%, &, =, etc”.

É importante também usar o gerador de URL para o Google Play para criar a URL dentro do padrão esperado (Link 1, Link 2):

Se você deseja simular isso no Android, sem ter que instalar o aplicativo pela loja, afim de testar o funcionamento, execute os comandos abaixo trocando os parâmetros (Link):

adb shell 
am broadcast -a com.android.vending.INSTALL_REFERRER -n <your.package>/.<path.up.until.your.BroadcastReceiver> --es "referrer" "utm_source=test_source\&utm_medium=test_medium\&utm_term=test_term\&utm_content=test_content\&utm_campaign=test_name"

E caso você queira criar seu Broadcast Receiver crie uma classe com o conteúdo:

public class InstallReferrerReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String referrer = intent.getStringExtra("referrer");

        //Use the referrer
    }
}

E no seu AndroidManifest.xml adicione:

<receiver
    android:name="com.example.android.InstallReferrerReceiver"
    android:exported="true">
    <intent-filter>
        <action android:name="com.android.vending.INSTALL_REFERRER" />
    </intent-filter>
</receiver>

 

 

Como funciona no caso do AppsFlyer:

Agora que você já entendeu como as plataformas se utilizam desses recursos, veja como o AppsFlyer mostrou esse funcionamento na rede deles:

Links:

https://support.appsflyer.com/hc/en-us/articles/207032096-Accessing-AppsFlyer-Attribution-Conversion-Data-from-the-SDK-Deferred-Deeplinking-

https://support.appsflyer.com/hc/en-us/articles/207032146-How-Can-I-Get-the-Install-Referrer-URL-from-my-Android-App-Context-

Imagem:

appsflyer-attribution-data

 

No caso do Google, basicamente o usuário vai clicar em um link como este:

app.appsflyer.com/angry-birds-android?pid=tapjoy_int&clickid=1020fe4c7e875&c=Ad1&af_siteid=2684

E quando o Broadcast Receiver for notificado, irá receber algo como:

af_tranid=3M69WKEKDHFPRXPG&pid=tapjoy_int&clickid=1020fe4c7e875&c=Ad1&af_siteid=2684

O AppsFlyer também possui uma aplicação para testar as campanhas antes de enviar o aplicativo para a loja:

Para Android:

https://support.appsflyer.com/hc/en-us/articles/207032136-Testing-AppsFlyer-Android-SDK-Integration-Before-After-Submitting-to-Google-Play

Para iOS:

https://support.appsflyer.com/hc/en-us/articles/207032046-Testing-AppsFlyer-iOS-SDK-Integration-Before-Submitting-to-the-App-Store-

 

Funcionamento geral:

Há diversas formas de fazer este tracking, como por exemplo, por IP. Mas usuários que usam WIFI ou estão dentro de redes específicas podem ter o mesmo IP de saída e esta regra acaba falhando.

O IDFA, no caso da Apple, ajuda neste sentido, pois você sabe quem é o usuário pois o mesmo IDFA clicado é o mesmo que gerou o evento após o aplicativo ser aberto.

É claro que as informações podem se perder, o usuário podem nem mesmo abrir o aplicativo, um problema de conexão pode impedir o envio dos dados, ou ele pode simplesmente desinstalar, enfim, como regra geral essas técnicas funcionam bem e fica fácil entender como este processo funciona agora.

 

Espero ter ajudado com este artigo.

Obrigado e até o próximo post pessoal.

Golandy – Game multiplayer open-source em HTML5 com Phaser + Golang e WebSocket – Versão para desktop, browser, android e iOS

Olá pessoal,

A um tempinho atrás fiz um game bem simples, usando HTML5 + Phaser e Go + WebSocket.

Fiz também os arquivos necessários para rodar o projeto tanto em desktop, web, android e iOS usando o Apache Cordova.

O link do game rodando é:

http://golandy.prsolucoes.com

Os links para baixar se encontram no meu Github, segue:

Cliente: https://github.com/prsolucoes/golandy-web

Servidor: https://github.com/prsolucoes/golandy-server

 

Sobre o jogo, ele é um tipo de clone do clássico bomberman. É multiplayer em tempo real. Fiz usando a engine Phaser e o servidor em Go. Toda a comunicação usa WebSocket e a versão nativa do Google, pois o desempenho da versão Gorilla é horrível.

Os mapas podem ser editados usando o MapEditor/Tiled (padrão tmx).

O game funciona no navegador, no desktop, no android, no iOS e onde mais o Apache Cordova suportar, pois como é em HTML5, qualquer browser roda ele. Em casa por exemplo, minha filha joga na TV.

É claro que o jogo não é perfeito e a comunidade da engine não ajuda muito.

Segue imagem:

Golandy Game Screenshot

 

Espero com este projeto, que a idéia e a arquitetura possam servir de inspiração para outros projetos e trabalhos.

Obrigado e até o próximo post pessoal.