├── .gitattributes ├── .gitignore ├── .scrutinizer.yml ├── .test.php ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── Makefile ├── README.md ├── Vagrantfile ├── codeception.yml ├── composer.json ├── provision ├── dot │ ├── .bash_aliases │ ├── .bash_git │ └── .vimrc ├── exec-always │ └── .gitignore ├── exec-once │ ├── 0.base.sh │ └── 1.composer.sh ├── init.sh ├── postinstall.sh └── shell │ ├── dot-files.sh │ └── execute-files.sh ├── src ├── ElasticsearchTarget.php ├── LogstashFileTarget.php ├── LogstashTarget.php ├── RedisTarget.php └── base │ ├── EmergencyTrait.php │ └── TargetTrait.php └── tests ├── _bootstrap.php ├── _helpers └── CodeHelper.php ├── _log └── .gitignore ├── _runtime └── .gitignore ├── unit.suite.yml └── unit ├── CodeGuy.php ├── ElasticsearchCest.php ├── LogstashCest.php ├── LogstashFileCest.php ├── RedisCest.php ├── _bootstrap.php └── _config.php /.gitattributes: -------------------------------------------------------------------------------- 1 | # Autodetect text files 2 | 3 | # Force the following filetypes to have unix eols, so Windows does not break them 4 | *.pp text eol=lf 5 | *.sh text eol=lf 6 | *.yaml text eol=lf 7 | Puppetfile text eol=lf 8 | .bash_aliases text eol=lf 9 | .vimrc text eol=lf 10 | .bash_git eol=lf 11 | .profile eol=lf 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | !.gitignore 2 | 3 | .vagrant 4 | .idea 5 | tests/_runtime 6 | tests/_log 7 | vendor 8 | composer.lock 9 | -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | filter: 2 | excluded_paths: 3 | - 'vendor/*' 4 | - 'tests/*' 5 | tools: 6 | external_code_coverage: 7 | timeout: 600 8 | php_code_sniffer: 9 | config: 10 | standard: PSR2 11 | sniffs: { psr1: { classes: { class_declaration_sniff: true } }, generic: { code_analysis: { unused_function_parameter_sniff: true, unconditional_if_statement_sniff: true, for_loop_should_be_while_loop_sniff: true }, php: { disallow_short_open_tag_sniff: true, sapi_usage_sniff: true }, metrics: { cyclomatic_complexity_sniff: true, nesting_level_sniff: true } }, squiz: { operators: { comparison_operator_usage_sniff: true } } } 12 | php_analyzer: 13 | enabled: true 14 | extensions: 15 | - php 16 | filter: 17 | excluded_paths: 18 | - 'vendor/*' 19 | - 'tests/*' 20 | paths: { } 21 | php_cpd: 22 | excluded_dirs: 23 | - vendor 24 | - tests 25 | enabled: true 26 | command: phpcpd 27 | names: 28 | - '*.php' 29 | min_lines: 5 30 | min_tokens: 70 31 | filter: 32 | excluded_paths: 33 | - 'vendor/*' 34 | - 'tests/*' 35 | php_pdepend: 36 | excluded_dirs: 37 | - vendor 38 | - tests 39 | enabled: true 40 | command: pdepend 41 | configuration_file: null 42 | suffixes: 43 | - php 44 | changetracking: 45 | bug_patterns: 46 | - '\bfix(?:es|ed)?\b' 47 | feature_patterns: 48 | - '\badd(?:s|ed)?\b' 49 | - '\bimplement(?:s|ed)?\b' -------------------------------------------------------------------------------- /.test.php: -------------------------------------------------------------------------------- 1 | 5 | * @license https://raw.github.com/index0h/yii2-log/master/LICENSE 6 | */ 7 | 8 | require_once __DIR__ . '/vendor/codeception/codeception/autoload.php'; 9 | 10 | use Symfony\Component\Console\Application; 11 | 12 | $app = new Application('Codeception', Codeception\Codecept::VERSION); 13 | $app->add(new Codeception\Command\Run('run')); 14 | 15 | $app->run(); -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.4 5 | - 5.5 6 | - 5.6 7 | 8 | services: 9 | - redis-server 10 | - elasticsearch 11 | 12 | install: 13 | - composer self-update && composer --version 14 | - composer global require "fxp/composer-asset-plugin:1.0.1" 15 | - composer install 16 | 17 | script: 18 | - php ./.test.php run --coverage-xml --quiet 19 | 20 | after_script: 21 | - wget https://scrutinizer-ci.com/ocular.phar 22 | - php ocular.phar code-coverage:upload --format=php-clover ./tests/_log/coverage.xml 23 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | yii2-log change log 2 | =================== 3 | 4 | 0.0.3 5 | 6 | * Update provision 7 | * Composer Yii version 8 | * Upgrade yii2 ref + add extra context field 9 | 10 | 0.0.2 11 | ----- 12 | 13 | * Full refactoring of redis and elasticsearch backends 14 | * Moving extension files ot src folder 15 | * Fixed logger (Yii 2.0.0-beta) 16 | * Updated codeception version 17 | 18 | 0.0.1 19 | ----- 20 | 21 | * #1 Implement base components 22 | * #2 Implement Logstash file transport 23 | * #3 Implement Logstash socket transport 24 | * #4 Implement Elsaticsearch transport 25 | * #5 Implement Redis transport 26 | * #7 Create codeception tests 27 | * #6 Write README 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Roman Levishchenko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | test: 3 | php ./.test.php run --coverage-xml --quiet 4 | 5 | .PHONY: test 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | yii2-log 2 | ======= 3 | 4 | [![Build Status](https://travis-ci.org/index0h/yii2-log.png?branch=master)](https://travis-ci.org/index0h/yii2-log) [![Latest Stable Version](https://poser.pugx.org/index0h/yii2-log/v/stable.png)](https://packagist.org/packages/index0h/yii2-log) [![Dependency Status](https://gemnasium.com/index0h/yii2-log.png)](https://gemnasium.com/index0h/yii2-log) [![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/index0h/yii2-log/badges/quality-score.png?s=305ee4c827a791ab27895799d2c3f3ce9553ea51)](https://scrutinizer-ci.com/g/index0h/yii2-log/) [![Code Coverage](https://scrutinizer-ci.com/g/index0h/yii2-log/badges/coverage.png?s=25e175d218529b7ffa0a2f39cb9204e5b4816843)](https://scrutinizer-ci.com/g/index0h/yii2-log/) [![Total Downloads](https://poser.pugx.org/index0h/yii2-log/downloads.png)](https://packagist.org/packages/index0h/yii2-log) [![License](https://poser.pugx.org/index0h/yii2-log/license.png)](https://packagist.org/packages/index0h/yii2-log) 5 | 6 | Different Yii2 log transports 7 | 8 | ## Now available 9 | 10 | * ElasticsearchTarget 11 | * LogstashFileTarget 12 | * LogstashTarget 13 | * RedisTarget 14 | 15 | ## Installation 16 | 17 | The preferred way to install this extension is through [composer](http://getcomposer.org/download/). 18 | 19 | ```sh 20 | php composer.phar require --prefer-dist index0h/yii2-log "0.0.3" 21 | ``` 22 | 23 | or add line to require section of `composer.json` 24 | 25 | ```json 26 | "index0h/yii2-log": "0.0.3" 27 | ``` 28 | 29 | ## Usage 30 | 31 | ### Common properties 32 | 33 | * `$emergencyLogFile`, default `@app/logs/logService.log` 34 | 35 | Elasticsearch, Redis and Logstash - are external services, so if they down our logs must be stored in file. 36 | For that **ElasticsearchTarget**, **LogstashTarget**, **RedisTarget** have option `$emergencyLogFile`. It's alias to 37 | file where logs will be written on log service is down. 38 | 39 | ### ElasticsearchTarget 40 | 41 | Stores logs in elasticsearch. All logs transform to json, so you can simply watch them by [kibana](http://www.elasticsearch.org/overview/kibana/). 42 | 43 | Extends yii\log\Target, more options see [here](https://github.com/yiisoft/yii2/blob/master/framework/log/Target.php) 44 | 45 | ##### Example configuration 46 | 47 | ```php 48 | .... 49 | 'components' => [ 50 | 'log' => [ 51 | 'targets' => [ 52 | ['class' => 'index0h\\log\\ElasticsearchTarget'], 53 | .... 54 | ``` 55 | 56 | ##### Properties 57 | 58 | * `index`, default 'yii' - Elasticsearch index name. 59 | * `type`, default 'log' - Elasticsearch index type. 60 | * `componentName` - Name of yii redis component. 61 | 62 | ### LogstashFileTarget 63 | 64 | Extends yii\log\FileTarget, more options see [here](https://github.com/yiisoft/yii2/blob/master/framework/log/FileTarget.php) 65 | 66 | ##### Example Yii configuration 67 | 68 | ```php 69 | .... 70 | 'components' => [ 71 | 'log' => [ 72 | 'targets' => [ 73 | ['class' => 'index0h\\log\\LogstashFileTarget'], 74 | .... 75 | ``` 76 | 77 | ##### Example Logstash configuration [(current version 1.3.3)](http://logstash.net/docs/1.3.3/) 78 | 79 | ``` 80 | input { 81 | file { 82 | type => "yii_log" 83 | path => [ "path/to/yii/logs/*.log*" ] 84 | start_position => "end" 85 | stat_interval => 1 86 | discover_interval => 30 87 | codec => "json" 88 | } 89 | } 90 | 91 | filter { 92 | # ... 93 | } 94 | 95 | output { 96 | stdout => {} 97 | } 98 | ``` 99 | 100 | ### LogstashTarget 101 | 102 | Extends yii\log\Target, more options see [here](https://github.com/yiisoft/yii2/blob/master/framework/log/Target.php) 103 | 104 | ##### Example Yii configuration 105 | 106 | ```php 107 | .... 108 | 'components' => [ 109 | 'log' => [ 110 | 'targets' => [ 111 | ['class' => 'index0h\\log\\LogstashTarget'], 112 | // Or UDP. 113 | [ 114 | 'class' => 'index0h\\log\\LogstashTarget', 115 | 'dsn' => 'udp://localhost:3333' 116 | ], 117 | // Or unix socket file. 118 | [ 119 | 'class' => 'index0h\\log\\LogstashTarget', 120 | 'dsn' => 'unix:///path/to/logstash.sock' 121 | ], 122 | .... 123 | ``` 124 | 125 | ##### Example Logstash configuration [(current version 1.3.3)](http://logstash.net/docs/1.3.3/) 126 | 127 | ``` 128 | input { 129 | tcp { 130 | type => "yii_log" 131 | port => 3333 132 | codec => "json" 133 | } 134 | # Or UDP. 135 | udp { 136 | type => "yii_log" 137 | port => 3333 138 | codec => "json" 139 | } 140 | # Or unix socket file. 141 | unix { 142 | type => "yii_log" 143 | path => "path/to/logstash.sock" 144 | codec => "json" 145 | } 146 | } 147 | 148 | filter { 149 | # ... 150 | } 151 | 152 | output { 153 | stdout => {} 154 | } 155 | ``` 156 | 157 | 158 | ##### Properties 159 | 160 | * `dsn`, default `tcp://localhost:3333` - URL to logstash service. Allowed schemas: 161 | **tcp**, **udp**, **unix** - for unix sock files. 162 | 163 | ### RedisTarget 164 | 165 | Extends yii\log\Target, more options see [here](https://github.com/yiisoft/yii2/blob/master/framework/log/Target.php) 166 | 167 | ##### Example Yii configuration 168 | 169 | ```php 170 | .... 171 | 'components' => [ 172 | 'log' => [ 173 | 'targets' => [ 174 | ['class' => 'index0h\\log\\RedisTarget'], 175 | .... 176 | ``` 177 | 178 | ##### Example Logstash configuration [(current version 1.3.3)](http://logstash.net/docs/1.3.3/) 179 | 180 | ``` 181 | input { 182 | redis { 183 | type => "yii_log" 184 | key => "yii_log" 185 | codec => "json" 186 | } 187 | } 188 | 189 | filter { 190 | # ... 191 | } 192 | 193 | output { 194 | stdout => {} 195 | } 196 | ``` 197 | 198 | ##### Properties 199 | 200 | * `key`, default `yii_log` - Redis list key. 201 | * `componentName` - Name of yii redis component. 202 | 203 | ## Testing 204 | 205 | #### Run tests from IDE (example for PhpStorm) 206 | 207 | - Select Run/Debug Configuration -> Edit Configurations 208 | - Select Add New Configuration -> PHP Script 209 | - Type: 210 | * File: /path/to/yii-phar/.test.php 211 | * Arguments run: run --coverage --html 212 | - OK 213 | 214 | #### Run tests from console 215 | 216 | ```sh 217 | make test 218 | ``` 219 | 220 | -- -- 221 | 222 | #### Thanks to 223 | 224 | [@achretien](https://github.com/achretien) 225 | [@Archy812](https://github.com/Archy812) 226 | [@xt99](https://github.com/xt99) -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | VAGRANTFILE_API_VERSION = "2" 2 | 3 | dir = File.dirname(File.expand_path(__FILE__)) 4 | 5 | Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| 6 | config.vm.box = "ubuntu/trusty64" 7 | 8 | config.vm.hostname = "yii2-log-pro" 9 | 10 | config.vm.network "private_network", ip: "192.168.100.117" 11 | 12 | config.vm.synced_folder "./", "/home/vagrant/work" 13 | 14 | config.vm.provider "virtualbox" do |vb| 15 | vb.customize ["modifyvm", :id, "--memory", "1024"] 16 | end 17 | 18 | config.vm.provision "shell", path: "provision/init.sh" 19 | end 20 | -------------------------------------------------------------------------------- /codeception.yml: -------------------------------------------------------------------------------- 1 | paths: 2 | tests: tests 3 | log: tests/_log 4 | data: tests/_data 5 | helpers: tests/_helpers 6 | settings: 7 | bootstrap: _bootstrap.php 8 | suite_class: \PHPUnit_Framework_TestSuite 9 | colors: true 10 | memory_limit: 1024M 11 | log: true 12 | coverage: 13 | enabled: true 14 | include: 15 | - src/* -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "index0h/yii2-log", 3 | "description": "Many Yii2 log targets", 4 | "version": "0.0.3", 5 | "type": "yii2-extension", 6 | "keywords": ["yii2", "log", "yii2-log", "log-target", "logstash", "elasticsearch", "redis"], 7 | "homepage": "https://github.com/index0h/yii2-log", 8 | "license": "MIT", 9 | "authors": [ 10 | { 11 | "name": "Roman Levishchenko", 12 | "email": "index.0h@gmail.com" 13 | } 14 | ], 15 | "support": { 16 | "issues": "https://github.com/index0h/yii2-log/issues", 17 | "source": "https://github.com/index0h/yii2-log" 18 | }, 19 | "require": { 20 | "php": ">=5.4.0", 21 | "yiisoft/yii2-composer": "2.0.*", 22 | "yiisoft/yii2": "2.0.*" 23 | }, 24 | "require-dev": { 25 | "codeception/codeception": "2.0.*", 26 | "yiisoft/yii2-redis": "2.0.*", 27 | "yiisoft/yii2-elasticsearch": "2.0.*" 28 | }, 29 | "autoload": { 30 | "psr-4": { 31 | "index0h\\log\\": "src" 32 | } 33 | }, 34 | "scripts": { 35 | "post-create-project-cmd": [ 36 | "yii\\composer\\Installer::setPermission" 37 | ] 38 | }, 39 | "config": { 40 | "process-timeout": 1800 41 | }, 42 | "extra": { 43 | "writable": [ 44 | "tests/_runtime", 45 | "tests/_log" 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /provision/dot/.bash_aliases: -------------------------------------------------------------------------------- 1 | if [ -f /etc/bash_completion ]; then 2 | source /etc/bash_completion 3 | fi 4 | 5 | __has_parent_dir () { 6 | # Utility function so we can test for things like .git/.hg without firing up a 7 | # separate process 8 | test -d "$1" && return 0; 9 | 10 | current="." 11 | while [ ! "$current" -ef "$current/.." ]; do 12 | if [ -d "$current/$1" ]; then 13 | return 0; 14 | fi 15 | current="$current/.."; 16 | done 17 | 18 | return 1; 19 | } 20 | 21 | __vcs_name() { 22 | if [ -d .svn ]; then 23 | echo "-[svn]"; 24 | elif __has_parent_dir ".git"; then 25 | echo "-[$(__git_ps1 'git %s')]"; 26 | elif __has_parent_dir ".hg"; then 27 | echo "-[hg $(hg branch)]" 28 | fi 29 | } 30 | 31 | black=$(tput -Txterm setaf 0) 32 | red=$(tput -Txterm setaf 1) 33 | green=$(tput -Txterm setaf 2) 34 | yellow=$(tput -Txterm setaf 3) 35 | dk_blue=$(tput -Txterm setaf 4) 36 | pink=$(tput -Txterm setaf 5) 37 | lt_blue=$(tput -Txterm setaf 6) 38 | 39 | bold=$(tput -Txterm bold) 40 | reset=$(tput -Txterm sgr0) 41 | 42 | # Nicely formatted terminal prompt 43 | export PS1='\n\[$bold\]\[$black\][\[$dk_blue\]\@\[$black\]]-[\[$green\]\u\[$yellow\]@\[$green\]\h\[$black\]]-[\[$pink\]\w\[$black\]]\[\033[0;33m\]$(__vcs_name) \[\033[00m\]\[$reset\]\n\[$reset\]\$ ' 44 | 45 | alias ls='ls -F --color=always' 46 | alias dir='dir -F --color=always' 47 | alias ll='ls -l' 48 | alias cp='cp -iv' 49 | alias rm='rm -i' 50 | alias mv='mv -iv' 51 | alias grep='grep --color=auto -in' 52 | alias ..='cd ..' 53 | -------------------------------------------------------------------------------- /provision/dot/.bash_git: -------------------------------------------------------------------------------- 1 | # bash/zsh git prompt support 2 | # 3 | # Copyright (C) 2006,2007 Shawn O. Pearce 4 | # Distributed under the GNU General Public License, version 2.0. 5 | # 6 | # This script allows you to see repository status in your prompt. 7 | # 8 | # To enable: 9 | # 10 | # 1) Copy this file to somewhere (e.g. ~/.git-prompt.sh). 11 | # 2) Add the following line to your .bashrc/.zshrc: 12 | # source ~/.git-prompt.sh 13 | # 3a) Change your PS1 to call __git_ps1 as 14 | # command-substitution: 15 | # Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ ' 16 | # ZSH: setopt PROMPT_SUBST ; PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ ' 17 | # the optional argument will be used as format string. 18 | # 3b) Alternatively, for a slightly faster prompt, __git_ps1 can 19 | # be used for PROMPT_COMMAND in Bash or for precmd() in Zsh 20 | # with two parameters,
 and , which are strings
 21 | #        you would put in $PS1 before and after the status string
 22 | #        generated by the git-prompt machinery.  e.g.
 23 | #        Bash: PROMPT_COMMAND='__git_ps1 "\u@\h:\w" "\\\$ "'
 24 | #          will show username, at-sign, host, colon, cwd, then
 25 | #          various status string, followed by dollar and SP, as
 26 | #          your prompt.
 27 | #        ZSH:  precmd () { __git_ps1 "%n" ":%~$ " "|%s" }
 28 | #          will show username, pipe, then various status string,
 29 | #          followed by colon, cwd, dollar and SP, as your prompt.
 30 | #        Optionally, you can supply a third argument with a printf
 31 | #        format string to finetune the output of the branch status
 32 | #
 33 | # The repository status will be displayed only if you are currently in a
 34 | # git repository. The %s token is the placeholder for the shown status.
 35 | #
 36 | # The prompt status always includes the current branch name.
 37 | #
 38 | # In addition, if you set GIT_PS1_SHOWDIRTYSTATE to a nonempty value,
 39 | # unstaged (*) and staged (+) changes will be shown next to the branch
 40 | # name.  You can configure this per-repository with the
 41 | # bash.showDirtyState variable, which defaults to true once
 42 | # GIT_PS1_SHOWDIRTYSTATE is enabled.
 43 | #
 44 | # You can also see if currently something is stashed, by setting
 45 | # GIT_PS1_SHOWSTASHSTATE to a nonempty value. If something is stashed,
 46 | # then a '$' will be shown next to the branch name.
 47 | #
 48 | # If you would like to see if there're untracked files, then you can set
 49 | # GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're untracked
 50 | # files, then a '%' will be shown next to the branch name.  You can
 51 | # configure this per-repository with the bash.showUntrackedFiles
 52 | # variable, which defaults to true once GIT_PS1_SHOWUNTRACKEDFILES is
 53 | # enabled.
 54 | #
 55 | # If you would like to see the difference between HEAD and its upstream,
 56 | # set GIT_PS1_SHOWUPSTREAM="auto".  A "<" indicates you are behind, ">"
 57 | # indicates you are ahead, "<>" indicates you have diverged and "="
 58 | # indicates that there is no difference. You can further control
 59 | # behaviour by setting GIT_PS1_SHOWUPSTREAM to a space-separated list
 60 | # of values:
 61 | #
 62 | #     verbose       show number of commits ahead/behind (+/-) upstream
 63 | #     name          if verbose, then also show the upstream abbrev name
 64 | #     legacy        don't use the '--count' option available in recent
 65 | #                   versions of git-rev-list
 66 | #     git           always compare HEAD to @{upstream}
 67 | #     svn           always compare HEAD to your SVN upstream
 68 | #
 69 | # By default, __git_ps1 will compare HEAD to your SVN upstream if it can
 70 | # find one, or @{upstream} otherwise.  Once you have set
 71 | # GIT_PS1_SHOWUPSTREAM, you can override it on a per-repository basis by
 72 | # setting the bash.showUpstream config variable.
 73 | #
 74 | # If you would like to see more information about the identity of
 75 | # commits checked out as a detached HEAD, set GIT_PS1_DESCRIBE_STYLE
 76 | # to one of these values:
 77 | #
 78 | #     contains      relative to newer annotated tag (v1.6.3.2~35)
 79 | #     branch        relative to newer tag or branch (master~4)
 80 | #     describe      relative to older annotated tag (v1.6.3.1-13-gdd42c2f)
 81 | #     default       exactly matching tag
 82 | #
 83 | # If you would like a colored hint about the current dirty state, set
 84 | # GIT_PS1_SHOWCOLORHINTS to a nonempty value. The colors are based on
 85 | # the colored output of "git status -sb" and are available only when
 86 | # using __git_ps1 for PROMPT_COMMAND or precmd.
 87 | 
 88 | # check whether printf supports -v
 89 | __git_printf_supports_v=
 90 | printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1
 91 | 
 92 | # stores the divergence from upstream in $p
 93 | # used by GIT_PS1_SHOWUPSTREAM
 94 | __git_ps1_show_upstream ()
 95 | {
 96 | 	local key value
 97 | 	local svn_remote svn_url_pattern count n
 98 | 	local upstream=git legacy="" verbose="" name=""
 99 | 
100 | 	svn_remote=()
101 | 	# get some config options from git-config
102 | 	local output="$(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ')"
103 | 	while read -r key value; do
104 | 		case "$key" in
105 | 		bash.showupstream)
106 | 			GIT_PS1_SHOWUPSTREAM="$value"
107 | 			if [[ -z "${GIT_PS1_SHOWUPSTREAM}" ]]; then
108 | 				p=""
109 | 				return
110 | 			fi
111 | 			;;
112 | 		svn-remote.*.url)
113 | 			svn_remote[$((${#svn_remote[@]} + 1))]="$value"
114 | 			svn_url_pattern="$svn_url_pattern\\|$value"
115 | 			upstream=svn+git # default upstream is SVN if available, else git
116 | 			;;
117 | 		esac
118 | 	done <<< "$output"
119 | 
120 | 	# parse configuration values
121 | 	for option in ${GIT_PS1_SHOWUPSTREAM}; do
122 | 		case "$option" in
123 | 		git|svn) upstream="$option" ;;
124 | 		verbose) verbose=1 ;;
125 | 		legacy)  legacy=1  ;;
126 | 		name)    name=1 ;;
127 | 		esac
128 | 	done
129 | 
130 | 	# Find our upstream
131 | 	case "$upstream" in
132 | 	git)    upstream="@{upstream}" ;;
133 | 	svn*)
134 | 		# get the upstream from the "git-svn-id: ..." in a commit message
135 | 		# (git-svn uses essentially the same procedure internally)
136 | 		local -a svn_upstream
137 | 		svn_upstream=($(git log --first-parent -1 \
138 | 					--grep="^git-svn-id: \(${svn_url_pattern#??}\)" 2>/dev/null))
139 | 		if [[ 0 -ne ${#svn_upstream[@]} ]]; then
140 | 			svn_upstream=${svn_upstream[${#svn_upstream[@]} - 2]}
141 | 			svn_upstream=${svn_upstream%@*}
142 | 			local n_stop="${#svn_remote[@]}"
143 | 			for ((n=1; n <= n_stop; n++)); do
144 | 				svn_upstream=${svn_upstream#${svn_remote[$n]}}
145 | 			done
146 | 
147 | 			if [[ -z "$svn_upstream" ]]; then
148 | 				# default branch name for checkouts with no layout:
149 | 				upstream=${GIT_SVN_ID:-git-svn}
150 | 			else
151 | 				upstream=${svn_upstream#/}
152 | 			fi
153 | 		elif [[ "svn+git" = "$upstream" ]]; then
154 | 			upstream="@{upstream}"
155 | 		fi
156 | 		;;
157 | 	esac
158 | 
159 | 	# Find how many commits we are ahead/behind our upstream
160 | 	if [[ -z "$legacy" ]]; then
161 | 		count="$(git rev-list --count --left-right \
162 | 				"$upstream"...HEAD 2>/dev/null)"
163 | 	else
164 | 		# produce equivalent output to --count for older versions of git
165 | 		local commits
166 | 		if commits="$(git rev-list --left-right "$upstream"...HEAD 2>/dev/null)"
167 | 		then
168 | 			local commit behind=0 ahead=0
169 | 			for commit in $commits
170 | 			do
171 | 				case "$commit" in
172 | 				"<"*) ((behind++)) ;;
173 | 				*)    ((ahead++))  ;;
174 | 				esac
175 | 			done
176 | 			count="$behind	$ahead"
177 | 		else
178 | 			count=""
179 | 		fi
180 | 	fi
181 | 
182 | 	# calculate the result
183 | 	if [[ -z "$verbose" ]]; then
184 | 		case "$count" in
185 | 		"") # no upstream
186 | 			p="" ;;
187 | 		"0	0") # equal to upstream
188 | 			p="=" ;;
189 | 		"0	"*) # ahead of upstream
190 | 			p=">" ;;
191 | 		*"	0") # behind upstream
192 | 			p="<" ;;
193 | 		*)	    # diverged from upstream
194 | 			p="<>" ;;
195 | 		esac
196 | 	else
197 | 		case "$count" in
198 | 		"") # no upstream
199 | 			p="" ;;
200 | 		"0	0") # equal to upstream
201 | 			p=" u=" ;;
202 | 		"0	"*) # ahead of upstream
203 | 			p=" u+${count#0	}" ;;
204 | 		*"	0") # behind upstream
205 | 			p=" u-${count%	0}" ;;
206 | 		*)	    # diverged from upstream
207 | 			p=" u+${count#*	}-${count%	*}" ;;
208 | 		esac
209 | 		if [[ -n "$count" && -n "$name" ]]; then
210 | 			__git_ps1_upstream_name=$(git rev-parse \
211 | 				--abbrev-ref "$upstream" 2>/dev/null)
212 | 			if [ $pcmode = yes ]; then
213 | 				# see the comments around the
214 | 				# __git_ps1_branch_name variable below
215 | 				p="$p \${__git_ps1_upstream_name}"
216 | 			else
217 | 				p="$p ${__git_ps1_upstream_name}"
218 | 				# not needed anymore; keep user's
219 | 				# environment clean
220 | 				unset __git_ps1_upstream_name
221 | 			fi
222 | 		fi
223 | 	fi
224 | 
225 | }
226 | 
227 | # Helper function that is meant to be called from __git_ps1.  It
228 | # injects color codes into the appropriate gitstring variables used
229 | # to build a gitstring.
230 | __git_ps1_colorize_gitstring ()
231 | {
232 | 	if [[ -n ${ZSH_VERSION-} ]]; then
233 | 		local c_red='%F{red}'
234 | 		local c_green='%F{green}'
235 | 		local c_lblue='%F{blue}'
236 | 		local c_clear='%f'
237 | 	else
238 | 		# Using \[ and \] around colors is necessary to prevent
239 | 		# issues with command line editing/browsing/completion!
240 | 		local c_red='\[\e[31m\]'
241 | 		local c_green='\[\e[32m\]'
242 | 		local c_lblue='\[\e[1;34m\]'
243 | 		local c_clear='\[\e[0m\]'
244 | 	fi
245 | 	local bad_color=$c_red
246 | 	local ok_color=$c_green
247 | 	local flags_color="$c_lblue"
248 | 
249 | 	local branch_color=""
250 | 	if [ $detached = no ]; then
251 | 		branch_color="$ok_color"
252 | 	else
253 | 		branch_color="$bad_color"
254 | 	fi
255 | 	c="$branch_color$c"
256 | 
257 | 	z="$c_clear$z"
258 | 	if [ "$w" = "*" ]; then
259 | 		w="$bad_color$w"
260 | 	fi
261 | 	if [ -n "$i" ]; then
262 | 		i="$ok_color$i"
263 | 	fi
264 | 	if [ -n "$s" ]; then
265 | 		s="$flags_color$s"
266 | 	fi
267 | 	if [ -n "$u" ]; then
268 | 		u="$bad_color$u"
269 | 	fi
270 | 	r="$c_clear$r"
271 | }
272 | 
273 | __git_eread ()
274 | {
275 | 	f="$1"
276 | 	shift
277 | 	test -r "$f" && read "$@" <"$f"
278 | }
279 | 
280 | # __git_ps1 accepts 0 or 1 arguments (i.e., format string)
281 | # when called from PS1 using command substitution
282 | # in this mode it prints text to add to bash PS1 prompt (includes branch name)
283 | #
284 | # __git_ps1 requires 2 or 3 arguments when called from PROMPT_COMMAND (pc)
285 | # in that case it _sets_ PS1. The arguments are parts of a PS1 string.
286 | # when two arguments are given, the first is prepended and the second appended
287 | # to the state string when assigned to PS1.
288 | # The optional third parameter will be used as printf format string to further
289 | # customize the output of the git-status string.
290 | # In this mode you can request colored hints using GIT_PS1_SHOWCOLORHINTS=true
291 | __git_ps1 ()
292 | {
293 | 	local pcmode=no
294 | 	local detached=no
295 | 	local ps1pc_start='\u@\h:\w '
296 | 	local ps1pc_end='\$ '
297 | 	local printf_format=' (%s)'
298 | 
299 | 	case "$#" in
300 | 		2|3)	pcmode=yes
301 | 			ps1pc_start="$1"
302 | 			ps1pc_end="$2"
303 | 			printf_format="${3:-$printf_format}"
304 | 		;;
305 | 		0|1)	printf_format="${1:-$printf_format}"
306 | 		;;
307 | 		*)	return
308 | 		;;
309 | 	esac
310 | 
311 | 	local repo_info rev_parse_exit_code
312 | 	repo_info="$(git rev-parse --git-dir --is-inside-git-dir \
313 | 		--is-bare-repository --is-inside-work-tree \
314 | 		--short HEAD 2>/dev/null)"
315 | 	rev_parse_exit_code="$?"
316 | 
317 | 	if [ -z "$repo_info" ]; then
318 | 		if [ $pcmode = yes ]; then
319 | 			#In PC mode PS1 always needs to be set
320 | 			PS1="$ps1pc_start$ps1pc_end"
321 | 		fi
322 | 		return
323 | 	fi
324 | 
325 | 	local short_sha
326 | 	if [ "$rev_parse_exit_code" = "0" ]; then
327 | 		short_sha="${repo_info##*$'\n'}"
328 | 		repo_info="${repo_info%$'\n'*}"
329 | 	fi
330 | 	local inside_worktree="${repo_info##*$'\n'}"
331 | 	repo_info="${repo_info%$'\n'*}"
332 | 	local bare_repo="${repo_info##*$'\n'}"
333 | 	repo_info="${repo_info%$'\n'*}"
334 | 	local inside_gitdir="${repo_info##*$'\n'}"
335 | 	local g="${repo_info%$'\n'*}"
336 | 
337 | 	local r=""
338 | 	local b=""
339 | 	local step=""
340 | 	local total=""
341 | 	if [ -d "$g/rebase-merge" ]; then
342 | 		__git_eread "$g/rebase-merge/head-name" b
343 | 		__git_eread "$g/rebase-merge/msgnum" step
344 | 		__git_eread "$g/rebase-merge/end" total
345 | 		if [ -f "$g/rebase-merge/interactive" ]; then
346 | 			r="|REBASE-i"
347 | 		else
348 | 			r="|REBASE-m"
349 | 		fi
350 | 	else
351 | 		if [ -d "$g/rebase-apply" ]; then
352 | 			__git_eread "$g/rebase-apply/next" step
353 | 			__git_eread "$g/rebase-apply/last" total
354 | 			if [ -f "$g/rebase-apply/rebasing" ]; then
355 | 				__git_eread "$g/rebase-apply/head-name" b
356 | 				r="|REBASE"
357 | 			elif [ -f "$g/rebase-apply/applying" ]; then
358 | 				r="|AM"
359 | 			else
360 | 				r="|AM/REBASE"
361 | 			fi
362 | 		elif [ -f "$g/MERGE_HEAD" ]; then
363 | 			r="|MERGING"
364 | 		elif [ -f "$g/CHERRY_PICK_HEAD" ]; then
365 | 			r="|CHERRY-PICKING"
366 | 		elif [ -f "$g/REVERT_HEAD" ]; then
367 | 			r="|REVERTING"
368 | 		elif [ -f "$g/BISECT_LOG" ]; then
369 | 			r="|BISECTING"
370 | 		fi
371 | 
372 | 		if [ -n "$b" ]; then
373 | 			:
374 | 		elif [ -h "$g/HEAD" ]; then
375 | 			# symlink symbolic ref
376 | 			b="$(git symbolic-ref HEAD 2>/dev/null)"
377 | 		else
378 | 			local head=""
379 | 			if ! __git_eread "$g/HEAD" head; then
380 | 				if [ $pcmode = yes ]; then
381 | 					PS1="$ps1pc_start$ps1pc_end"
382 | 				fi
383 | 				return
384 | 			fi
385 | 			# is it a symbolic ref?
386 | 			b="${head#ref: }"
387 | 			if [ "$head" = "$b" ]; then
388 | 				detached=yes
389 | 				b="$(
390 | 				case "${GIT_PS1_DESCRIBE_STYLE-}" in
391 | 				(contains)
392 | 					git describe --contains HEAD ;;
393 | 				(branch)
394 | 					git describe --contains --all HEAD ;;
395 | 				(describe)
396 | 					git describe HEAD ;;
397 | 				(* | default)
398 | 					git describe --tags --exact-match HEAD ;;
399 | 				esac 2>/dev/null)" ||
400 | 
401 | 				b="$short_sha..."
402 | 				b="($b)"
403 | 			fi
404 | 		fi
405 | 	fi
406 | 
407 | 	if [ -n "$step" ] && [ -n "$total" ]; then
408 | 		r="$r $step/$total"
409 | 	fi
410 | 
411 | 	local w=""
412 | 	local i=""
413 | 	local s=""
414 | 	local u=""
415 | 	local c=""
416 | 	local p=""
417 | 
418 | 	if [ "true" = "$inside_gitdir" ]; then
419 | 		if [ "true" = "$bare_repo" ]; then
420 | 			c="BARE:"
421 | 		else
422 | 			b="GIT_DIR!"
423 | 		fi
424 | 	elif [ "true" = "$inside_worktree" ]; then
425 | 		if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ] &&
426 | 		   [ "$(git config --bool bash.showDirtyState)" != "false" ]
427 | 		then
428 | 			git diff --no-ext-diff --quiet --exit-code || w="*"
429 | 			if [ -n "$short_sha" ]; then
430 | 				git diff-index --cached --quiet HEAD -- || i="+"
431 | 			else
432 | 				i="#"
433 | 			fi
434 | 		fi
435 | 		if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ] &&
436 | 		   [ -r "$g/refs/stash" ]; then
437 | 			s="$"
438 | 		fi
439 | 
440 | 		if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ] &&
441 | 		   [ "$(git config --bool bash.showUntrackedFiles)" != "false" ] &&
442 | 		   git ls-files --others --exclude-standard --error-unmatch -- '*' >/dev/null 2>/dev/null
443 | 		then
444 | 			u="%${ZSH_VERSION+%}"
445 | 		fi
446 | 
447 | 		if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
448 | 			__git_ps1_show_upstream
449 | 		fi
450 | 	fi
451 | 
452 | 	local z="${GIT_PS1_STATESEPARATOR-" "}"
453 | 
454 | 	# NO color option unless in PROMPT_COMMAND mode
455 | 	if [ $pcmode = yes ] && [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then
456 | 		__git_ps1_colorize_gitstring
457 | 	fi
458 | 
459 | 	b=${b##refs/heads/}
460 | 	if [ $pcmode = yes ]; then
461 | 		# In pcmode (and only pcmode) the contents of
462 | 		# $gitstring are subject to expansion by the shell.
463 | 		# Avoid putting the raw ref name in the prompt to
464 | 		# protect the user from arbitrary code execution via
465 | 		# specially crafted ref names (e.g., a ref named
466 | 		# '$(IFS=_;cmd=sudo_rm_-rf_/;$cmd)' would execute
467 | 		# 'sudo rm -rf /' when the prompt is drawn).  Instead,
468 | 		# put the ref name in a new global variable (in the
469 | 		# __git_ps1_* namespace to avoid colliding with the
470 | 		# user's environment) and reference that variable from
471 | 		# PS1.
472 | 		__git_ps1_branch_name=$b
473 | 		# note that the $ is escaped -- the variable will be
474 | 		# expanded later (when it's time to draw the prompt)
475 | 		b="\${__git_ps1_branch_name}"
476 | 	fi
477 | 
478 | 	local f="$w$i$s$u"
479 | 	local gitstring="$c$b${f:+$z$f}$r$p"
480 | 
481 | 	if [ $pcmode = yes ]; then
482 | 		if [ "${__git_printf_supports_v-}" != yes ]; then
483 | 			gitstring=$(printf -- "$printf_format" "$gitstring")
484 | 		else
485 | 			printf -v gitstring -- "$printf_format" "$gitstring"
486 | 		fi
487 | 		PS1="$ps1pc_start$gitstring$ps1pc_end"
488 | 	else
489 | 		printf -- "$printf_format" "$gitstring"
490 | 	fi
491 | }
492 | 


--------------------------------------------------------------------------------
/provision/dot/.vimrc:
--------------------------------------------------------------------------------
  1 | set rtp+=$GOROOT/misc/vim
  2 | 
  3 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  4 | " Maintainer:
  5 | "       Amir Salihefendic
  6 | "       http://amix.dk - amix@amix.dk
  7 | "
  8 | " Version:
  9 | "       5.0 - 29/05/12 15:43:36
 10 | "
 11 | " Blog_post:
 12 | "       http://amix.dk/blog/post/19691#The-ultimate-Vim-configuration-on-Github
 13 | "
 14 | " Awesome_version:
 15 | "       Get this config, nice color schemes and lots of plugins!
 16 | "
 17 | "       Install the awesome version from:
 18 | "
 19 | "           https://github.com/amix/vimrc
 20 | "
 21 | " Syntax_highlighted:
 22 | "       http://amix.dk/vim/vimrc.html
 23 | "
 24 | " Raw_version:
 25 | "       http://amix.dk/vim/vimrc.txt
 26 | "
 27 | " Sections:
 28 | "    -> General
 29 | "    -> VIM user interface
 30 | "    -> Colors and Fonts
 31 | "    -> Files and backups
 32 | "    -> Text, tab and indent related
 33 | "    -> Visual mode related
 34 | "    -> Moving around, tabs and buffers
 35 | "    -> Status line
 36 | "    -> Editing mappings
 37 | "    -> vimgrep searching and cope displaying
 38 | "    -> Spell checking
 39 | "    -> Misc
 40 | "    -> Helper functions
 41 | "
 42 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 43 | 
 44 | 
 45 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 46 | " => General
 47 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 48 | " Sets how many lines of history VIM has to remember
 49 | set history=700
 50 | 
 51 | " Enable filetype plugins
 52 | filetype plugin on
 53 | filetype indent on
 54 | 
 55 | " Set to auto read when a file is changed from the outside
 56 | set autoread
 57 | 
 58 | " With a map leader it's possible to do extra key combinations
 59 | " like w saves the current file
 60 | let mapleader = ","
 61 | let g:mapleader = ","
 62 | 
 63 | " Fast saving
 64 | nmap w :w!
 65 | 
 66 | " :W sudo saves the file
 67 | " (useful for handling the permission-denied error)
 68 | command W w !sudo tee % > /dev/null
 69 | 
 70 | 
 71 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 72 | " => VIM user interface
 73 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 74 | " Set 7 lines to the cursor - when moving vertically using j/k
 75 | set so=7
 76 | 
 77 | " Turn on the WiLd menu
 78 | set wildmenu
 79 | 
 80 | " Ignore compiled files
 81 | set wildignore=*.o,*~,*.pyc
 82 | if has("win16") || has("win32")
 83 |     set wildignore+=*/.git/*,*/.hg/*,*/.svn/*,*/.DS_Store
 84 | else
 85 |     set wildignore+=.git\*,.hg\*,.svn\*
 86 | endif
 87 | 
 88 | "Always show current position
 89 | set ruler
 90 | 
 91 | " Height of the command bar
 92 | set cmdheight=2
 93 | 
 94 | " A buffer becomes hidden when it is abandoned
 95 | set hid
 96 | 
 97 | " Configure backspace so it acts as it should act
 98 | set backspace=eol,start,indent
 99 | set whichwrap+=<,>,h,l
100 | 
101 | " Ignore case when searching
102 | set ignorecase
103 | 
104 | " When searching try to be smart about cases
105 | set smartcase
106 | 
107 | " Highlight search results
108 | set hlsearch
109 | 
110 | " Makes search act like search in modern browsers
111 | set incsearch
112 | 
113 | " Don't redraw while executing macros (good performance config)
114 | set lazyredraw
115 | 
116 | " For regular expressions turn magic on
117 | set magic
118 | 
119 | " Show matching brackets when text indicator is over them
120 | set showmatch
121 | " How many tenths of a second to blink when matching brackets
122 | set mat=2
123 | 
124 | " No annoying sound on errors
125 | set noerrorbells
126 | set novisualbell
127 | set t_vb=
128 | set tm=500
129 | 
130 | " Add a bit extra margin to the left
131 | set foldcolumn=1
132 | 
133 | 
134 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
135 | " => Colors and Fonts
136 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
137 | " Enable syntax highlighting
138 | syntax enable
139 | 
140 | try
141 |     colorscheme desert
142 | catch
143 | endtry
144 | 
145 | set background=dark
146 | 
147 | " Set extra options when running in GUI mode
148 | if has("gui_running")
149 |     set guioptions-=T
150 |     set guioptions-=e
151 |     set t_Co=256
152 |     set guitablabel=%M\ %t
153 | endif
154 | 
155 | " Set utf8 as standard encoding and en_US as the standard language
156 | set encoding=utf8
157 | 
158 | " Use Unix as the standard file type
159 | set ffs=unix,dos,mac
160 | 
161 | 
162 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
163 | " => Files, backups and undo
164 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
165 | " Turn backup off, since most stuff is in SVN, git et.c anyway...
166 | set nobackup
167 | set nowb
168 | set noswapfile
169 | 
170 | 
171 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
172 | " => Text, tab and indent related
173 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
174 | " Use spaces instead of tabs
175 | set expandtab
176 | 
177 | " Be smart when using tabs ;)
178 | set smarttab
179 | 
180 | " 1 tab == 4 spaces
181 | set shiftwidth=4
182 | set tabstop=4
183 | 
184 | " Linebreak on 500 characters
185 | set lbr
186 | set tw=500
187 | 
188 | set ai "Auto indent
189 | set si "Smart indent
190 | set wrap "Wrap lines
191 | 
192 | 
193 | """"""""""""""""""""""""""""""
194 | " => Visual mode related
195 | """"""""""""""""""""""""""""""
196 | " Visual mode pressing * or # searches for the current selection
197 | " Super useful! From an idea by Michael Naumann
198 | vnoremap  * :call VisualSelection('f', '')
199 | vnoremap  # :call VisualSelection('b', '')
200 | 
201 | 
202 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
203 | " => Moving around, tabs, windows and buffers
204 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
205 | " Treat long lines as break lines (useful when moving around in them)
206 | map j gj
207 | map k gk
208 | 
209 | " Map  to / (search) and Ctrl- to ? (backwards search)
210 | map  /
211 | map  ?
212 | 
213 | " Disable highlight when  is pressed
214 | map   :noh
215 | 
216 | " Smart way to move between windows
217 | map  j
218 | map  k
219 | map  h
220 | map  l
221 | 
222 | " Close the current buffer
223 | map bd :Bclose
224 | 
225 | " Close all the buffers
226 | map ba :1,1000 bd!
227 | 
228 | " Useful mappings for managing tabs
229 | map tn :tabnew
230 | map to :tabonly
231 | map tc :tabclose
232 | map tm :tabmove
233 | map t :tabnext
234 | 
235 | " Opens a new tab with the current buffer's path
236 | " Super useful when editing files in the same directory
237 | map te :tabedit =expand("%:p:h")/
238 | 
239 | " Switch CWD to the directory of the open buffer
240 | map cd :cd %:p:h:pwd
241 | 
242 | " Specify the behavior when switching between buffers
243 | try
244 |   set switchbuf=useopen,usetab,newtab
245 |   set stal=2
246 | catch
247 | endtry
248 | 
249 | " Return to last edit position when opening files (You want this!)
250 | autocmd BufReadPost *
251 |      \ if line("'\"") > 0 && line("'\"") <= line("$") |
252 |      \   exe "normal! g`\"" |
253 |      \ endif
254 | " Remember info about open buffers on close
255 | set viminfo^=%
256 | 
257 | 
258 | """"""""""""""""""""""""""""""
259 | " => Status line
260 | """"""""""""""""""""""""""""""
261 | " Always show the status line
262 | set laststatus=2
263 | 
264 | " Format the status line
265 | set statusline=\ %{HasPaste()}%F%m%r%h\ %w\ \ CWD:\ %r%{getcwd()}%h\ \ \ Line:\ %l
266 | 
267 | 
268 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
269 | " => Editing mappings
270 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
271 | " Remap VIM 0 to first non-blank character
272 | map 0 ^
273 | 
274 | " Move a line of text using ALT+[jk] or Comamnd+[jk] on mac
275 | nmap  mz:m+`z
276 | nmap  mz:m-2`z
277 | vmap  :m'>+`mzgv`yo`z
278 | vmap  :m'<-2`>my` 
282 |   nmap  
283 |   vmap  
284 |   vmap  
285 | endif
286 | 
287 | " Delete trailing white space on save, useful for Python and CoffeeScript ;)
288 | func! DeleteTrailingWS()
289 |   exe "normal mz"
290 |   %s/\s\+$//ge
291 |   exe "normal `z"
292 | endfunc
293 | autocmd BufWrite *.py :call DeleteTrailingWS()
294 | autocmd BufWrite *.coffee :call DeleteTrailingWS()
295 | 
296 | 
297 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
298 | " => vimgrep searching and cope displaying
299 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
300 | " When you press gv you vimgrep after the selected text
301 | vnoremap  gv :call VisualSelection('gv', '')
302 | 
303 | " Open vimgrep and put the cursor in the right position
304 | map g :vimgrep // **/*.
305 | 
306 | " Vimgreps in the current file
307 | map  :vimgrep // %
308 | 
309 | " When you press r you can search and replace the selected text
310 | vnoremap  r :call VisualSelection('replace', '')
311 | 
312 | " Do :help cope if you are unsure what cope is. It's super useful!
313 | "
314 | " When you search with vimgrep, display your results in cope by doing:
315 | "   cc
316 | "
317 | " To go to the next search result do:
318 | "   n
319 | "
320 | " To go to the previous search results do:
321 | "   p
322 | "
323 | map cc :botright cope
324 | map co ggVGy:tabnew:set syntax=qfpgg
325 | map n :cn
326 | map p :cp
327 | 
328 | 
329 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
330 | " => Spell checking
331 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
332 | " Pressing ,ss will toggle and untoggle spell checking
333 | map ss :setlocal spell!
334 | 
335 | " Shortcuts using 
336 | map sn ]s
337 | map sp [s
338 | map sa zg
339 | map s? z=
340 | 
341 | 
342 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
343 | " => Misc
344 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
345 | " Remove the Windows ^M - when the encodings gets messed up
346 | noremap m mmHmt:%s///ge'tzt'm
347 | 
348 | " Quickly open a buffer for scripbble
349 | map q :e ~/buffer
350 | 
351 | " Toggle paste mode on and off
352 | map pp :setlocal paste!
353 | 
354 | 
355 | 
356 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
357 | " => Helper functions
358 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
359 | function! CmdLine(str)
360 |     exe "menu Foo.Bar :" . a:str
361 |     emenu Foo.Bar
362 |     unmenu Foo
363 | endfunction
364 | 
365 | function! VisualSelection(direction, extra_filter) range
366 |     let l:saved_reg = @"
367 |     execute "normal! vgvy"
368 | 
369 |     let l:pattern = escape(@", '\\/.*$^~[]')
370 |     let l:pattern = substitute(l:pattern, "\n$", "", "")
371 | 
372 |     if a:direction == 'b'
373 |         execute "normal ?" . l:pattern . "^M"
374 |     elseif a:direction == 'gv'
375 |         call CmdLine("vimgrep " . '/'. l:pattern . '/' . ' **/*.' . a:extra_filter)
376 |     elseif a:direction == 'replace'
377 |         call CmdLine("%s" . '/'. l:pattern . '/')
378 |     elseif a:direction == 'f'
379 |         execute "normal /" . l:pattern . "^M"
380 |     endif
381 | 
382 |     let @/ = l:pattern
383 |     let @" = l:saved_reg
384 | endfunction
385 | 
386 | 
387 | " Returns true if paste mode is enabled
388 | function! HasPaste()
389 |     if &paste
390 |         return 'PASTE MODE  '
391 |     en
392 |     return ''
393 | endfunction
394 | 
395 | " Don't close window, when deleting a buffer
396 | command! Bclose call BufcloseCloseIt()
397 | function! BufcloseCloseIt()
398 |    let l:currentBufNum = bufnr("%")
399 |    let l:alternateBufNum = bufnr("#")
400 | 
401 |    if buflisted(l:alternateBufNum)
402 |      buffer #
403 |    else
404 |      bnext
405 |    endif
406 | 
407 |    if bufnr("%") == l:currentBufNum
408 |      new
409 |    endif
410 | 
411 |    if buflisted(l:currentBufNum)
412 |      execute("bdelete! ".l:currentBufNum)
413 |    endif
414 | endfunction
415 | 


--------------------------------------------------------------------------------
/provision/exec-always/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/index0h/yii2-log/a470a913e953a190880ced04ddfa13fe2ecc4811/provision/exec-always/.gitignore


--------------------------------------------------------------------------------
/provision/exec-once/0.base.sh:
--------------------------------------------------------------------------------
 1 | #!/bin/sh
 2 | 
 3 | echo "Install basic packages"
 4 | 
 5 | wget -qO - https://packages.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
 6 | echo 'deb http://packages.elastic.co/elasticsearch/1.5/debian stable main' > /etc/apt/sources.list.d/elasticsearch.list
 7 | 
 8 | apt-get update > /dev/null 2>&1
 9 | apt-get install -y vim mc htop \
10 |     curl git mercurial \
11 |     redis-server openjdk-7-jre elasticsearch \
12 |     php5-xdebug php5-curl php-pear > /dev/null 2>&1
13 | 
14 | /etc/init.d/elasticsearch start


--------------------------------------------------------------------------------
/provision/exec-once/1.composer.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | 
3 | curl -sS https://getcomposer.org/installer | php
4 | mv composer.phar /usr/local/bin/composer
5 | 
6 | su - vagrant -c 'composer global require "fxp/composer-asset-plugin:1.0.1"'
7 | 
8 | su - vagrant -c 'cd /home/vagrant/work; composer install'


--------------------------------------------------------------------------------
/provision/init.sh:
--------------------------------------------------------------------------------
 1 | #!/bin/bash
 2 | 
 3 | echo "Init"
 4 | 
 5 | export DEBIAN_FRONTEND=noninteractive
 6 | 
 7 | if [[ ! -d '/.provision-stuff' ]]; then
 8 |     mkdir '/.provision-stuff'
 9 |     echo 'Created directory /.provision-stuff'
10 | fi
11 | 
12 | bash /vagrant/provision/shell/dot-files.sh
13 | bash /vagrant/provision/shell/execute-files.sh
14 | 


--------------------------------------------------------------------------------
/provision/postinstall.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | 
3 | updatedb
4 | 


--------------------------------------------------------------------------------
/provision/shell/dot-files.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | 
3 | cp -r /vagrant/provision/dot/.[a-zA-Z0-9]* /home/vagrant/
4 | chown -R vagrant:vagrant /home/vagrant/
5 | 
6 | cp -r /vagrant/provision/dot/.[a-zA-Z0-9]* /root/
7 | chown -R root:root /root/
8 | 


--------------------------------------------------------------------------------
/provision/shell/execute-files.sh:
--------------------------------------------------------------------------------
 1 | #!/bin/bash
 2 | 
 3 | export DEBIAN_FRONTEND=noninteractive
 4 | 
 5 | shopt -s nullglob
 6 | files=(/vagrant/provision/exec-once/*)
 7 | 
 8 | if [[ ! -f '/.provision-stuff/exec-once-ran' && (${#files[@]} -gt 0) ]]; then
 9 |     echo 'Running files in files/exec-once'
10 |     find "/vagrant/provision/exec-once" -maxdepth 1 -not -path '*/\.*' -type f \( ! -iname ".gitignore" \) -exec chmod +x '{}' \; -exec {} \;
11 |     echo 'Finished running files in files/exec-once'
12 |     echo 'To run again, delete file /.provision-stuff/exec-once-ran'
13 |     touch /.provision-stuff/exec-once-ran
14 | fi
15 | 
16 | echo 'Running files in files/exec-always'
17 | find "/vagrant/provision/exec-always" -maxdepth 1 -not -path '*/\.*' -type f \( ! -iname ".gitignore" \) -exec chmod +x '{}' \; -exec {} \;
18 | echo 'Finished running files in files/exec-always'
19 | 


--------------------------------------------------------------------------------
/src/ElasticsearchTarget.php:
--------------------------------------------------------------------------------
 1 | 
 5 |  * @license   https://raw.github.com/index0h/yii2-log/master/LICENSE
 6 |  */
 7 | 
 8 | namespace index0h\log;
 9 | 
10 | use index0h\log\base\EmergencyTrait;
11 | use index0h\log\base\TargetTrait;
12 | use yii\log\Target;
13 | 
14 | /**
15 |  * @author Roman Levishchenko 
16 |  */
17 | class ElasticsearchTarget extends Target
18 | {
19 |     use TargetTrait;
20 |     use EmergencyTrait;
21 | 
22 |     /** @var string Elasticsearch index name. */
23 |     public $index = 'yii';
24 | 
25 |     /** @var string Elasticsearch type name. */
26 |     public $type = 'log';
27 | 
28 |     /** @var string Yii Elasticsearch component name. */
29 |     public $componentName = 'elasticsearch';
30 | 
31 |     /**
32 |      * @inheritdoc
33 |      */
34 |     public function export()
35 |     {
36 |         try {
37 |             $messages = array_map([$this, 'formatMessage'], $this->messages);
38 |             foreach ($messages as &$message) {
39 |                 \Yii::$app->{$this->componentName}->post([$this->index, $this->type], [], $message);
40 |             }
41 |         } catch (\Exception $error) {
42 |             $this->emergencyExport(
43 |                 [
44 |                     'index' => $this->index,
45 |                     'type' => $this->type,
46 |                     'error' => $error->getMessage(),
47 |                     'errorNumber' => $error->getCode(),
48 |                     'trace' => $error->getTraceAsString()
49 |                 ]
50 |             );
51 |         }
52 |     }
53 | }
54 | 


--------------------------------------------------------------------------------
/src/LogstashFileTarget.php:
--------------------------------------------------------------------------------
 1 | 
 5 |  * @license   https://raw.github.com/index0h/yii2-log/master/LICENSE
 6 |  */
 7 | 
 8 | namespace index0h\log;
 9 | 
10 | use index0h\log\base\TargetTrait;
11 | 
12 | /**
13 |  * @author Roman Levishchenko 
14 |  */
15 | class LogstashFileTarget extends \yii\log\FileTarget
16 | {
17 |     use TargetTrait;
18 | }
19 | 


--------------------------------------------------------------------------------
/src/LogstashTarget.php:
--------------------------------------------------------------------------------
 1 | 
 5 |  * @license   https://raw.github.com/index0h/yii2-log/master/LICENSE
 6 |  */
 7 | 
 8 | namespace index0h\log;
 9 | 
10 | use index0h\log\base\EmergencyTrait;
11 | use index0h\log\base\TargetTrait;
12 | 
13 | /**
14 |  * @author Roman Levishchenko 
15 |  */
16 | class LogstashTarget extends \yii\log\Target
17 | {
18 |     use TargetTrait;
19 |     use EmergencyTrait;
20 | 
21 |     /** @var string Connection configuration to Logstash. */
22 |     public $dsn = 'tcp://localhost:3333';
23 | 
24 |     /**
25 |      * @inheritdoc
26 |      */
27 |     public function export()
28 |     {
29 |         try {
30 |             $socket = stream_socket_client($this->dsn, $errorNumber, $error, 30);
31 | 
32 |             foreach ($this->messages as &$message) {
33 |                 fwrite($socket, $this->formatMessage($message) . "\r\n");
34 |             }
35 | 
36 |             fclose($socket);
37 |         } catch (\Exception $error) {
38 |             $this->emergencyExport(
39 |                 [
40 |                     'dsn' => $this->dsn,
41 |                     'error' => $error->getMessage(),
42 |                     'errorNumber' => $error->getCode(),
43 |                     'trace' => $error->getTraceAsString()
44 |                 ]
45 |             );
46 |         }
47 |     }
48 | }
49 | 


--------------------------------------------------------------------------------
/src/RedisTarget.php:
--------------------------------------------------------------------------------
 1 | 
 5 |  * @license   https://raw.github.com/index0h/yii2-log/master/LICENSE
 6 |  */
 7 | 
 8 | namespace index0h\log;
 9 | 
10 | use index0h\log\base\EmergencyTrait;
11 | use index0h\log\base\TargetTrait;
12 | use yii\log\Target;
13 | 
14 | /**
15 |  * @author Roman Levishchenko 
16 |  */
17 | class RedisTarget extends Target
18 | {
19 |     use TargetTrait;
20 |     use EmergencyTrait;
21 | 
22 |     /** @var string Redis list key. */
23 |     public $key = 'yii_log';
24 | 
25 |     /** @var string Yii redis component name. */
26 |     public $componentName = 'redis';
27 | 
28 |     /**
29 |      * @inheritdoc
30 |      */
31 |     public function export()
32 |     {
33 |         try {
34 |             $messages = array_map([$this, 'formatMessage'], $this->messages);
35 |             foreach ($messages as &$message) {
36 |                 \Yii::$app->{$this->componentName}->lpush($this->key, $message);
37 |             }
38 |         } catch (\Exception $error) {
39 |             $this->emergencyExport(
40 |                 [
41 |                     'key' => $this->key,
42 |                     'error' => $error->getMessage(),
43 |                     'errorNumber' => $error->getCode(),
44 |                     'trace' => $error->getTraceAsString()
45 |                 ]
46 |             );
47 |         }
48 |     }
49 | }
50 | 


--------------------------------------------------------------------------------
/src/base/EmergencyTrait.php:
--------------------------------------------------------------------------------
 1 | 
 5 |  * @license   https://raw.github.com/index0h/yii2-log/master/LICENSE
 6 |  */
 7 | 
 8 | namespace index0h\log\base;
 9 | 
10 | use yii\helpers\ArrayHelper;
11 | 
12 | /**
13 |  * Current class needs to write logs on external service exception.
14 |  *
15 |  * @property array messages The messages that are retrieved from the logger so far by this log target.
16 |  *
17 |  * @author Roman Levishchenko 
18 |  */
19 | trait EmergencyTrait
20 | {
21 |     /** @var string Alias of log file. */
22 |     public $emergencyLogFile = '@runtime/logs/logService.log';
23 | 
24 |     /**
25 |      * @param array $data Additional information to log messages from target.
26 |      */
27 |     public function emergencyExport($data)
28 |     {
29 |         $this->emergencyPrepareMessages($data);
30 |         $text = implode("\n", array_map([$this, 'formatMessage'], $this->messages)) . "\n";
31 | 
32 |         file_put_contents(\Yii::getAlias($this->emergencyLogFile), $text, FILE_APPEND);
33 |     }
34 | 
35 |     /**
36 |      * @param array $data Additional information to log messages from target.
37 |      */
38 |     protected function emergencyPrepareMessages($data)
39 |     {
40 |         foreach ($this->messages as &$message) {
41 |             $message[0] = ArrayHelper::merge($message[0], ['emergency' => $data]);
42 |         }
43 |     }
44 | }


--------------------------------------------------------------------------------
/src/base/TargetTrait.php:
--------------------------------------------------------------------------------
  1 | 
  5 |  * @license   https://raw.github.com/index0h/yii2-log/master/LICENSE
  6 |  */
  7 | 
  8 | namespace index0h\log\base;
  9 | 
 10 | use yii\helpers\ArrayHelper;
 11 | use yii\log\Logger;
 12 | 
 13 | /**
 14 |  * @property string[]    categories     List of message categories that this target is interested in.
 15 |  * @property string[]    except         List of message categories that this target is NOT interested in
 16 |  * @property int         exportInterval How many messages should be accumulated before they are exported.
 17 |  * @property string[]    logVars        List of the PHP predefined variables that should be logged in a message.
 18 |  * @property array       messages       The messages that are retrieved from the logger so far by this log target.
 19 |  *
 20 |  * @method int getLevels() The message levels that this target is interested in.
 21 |  * @method array filterMessages(array $messages, int $levels, array $categories, array $except)
 22 |  *     Filters the given messages according to their categories and levels.
 23 |  * @method void export Exports log [[messages]] to a specific destination.
 24 |  *
 25 |  * @author Roman Levishchenko 
 26 |  */
 27 | trait TargetTrait
 28 | {
 29 |     /** @var bool Whether to log a message containing the current user name and ID. */
 30 |     public $logUser = false;
 31 | 
 32 |     /** @var array Add more context */
 33 |     public $context = [];
 34 | 
 35 |     /**
 36 |      * Processes the given log messages.
 37 |      *
 38 |      * @param array $messages Log messages to be processed.
 39 |      * @param bool  $final    Whether this method is called at the end of the current application
 40 |      */
 41 |     public function collect($messages, $final)
 42 |     {
 43 |         $this->messages = array_merge(
 44 |             $this->messages,
 45 |             $this->filterMessages($messages, $this->getLevels(), $this->categories, $this->except)
 46 |         );
 47 |         $count = count($this->messages);
 48 |         if (($count > 0) && (($final == true) || ($this->exportInterval > 0) && ($count >= $this->exportInterval))) {
 49 |             $this->addContextToMessages();
 50 |             $this->export();
 51 |             $this->messages = [];
 52 |         }
 53 |     }
 54 | 
 55 |     /**
 56 |      * Formats a log message.
 57 |      *
 58 |      * @param array $message The log message to be formatted.
 59 |      *
 60 |      * @return string
 61 |      */
 62 |     public function formatMessage($message)
 63 |     {
 64 |         return json_encode($this->prepareMessage($message));
 65 |     }
 66 | 
 67 |     /**
 68 |      * Updates all messages if there are context variables.
 69 |      */
 70 |     protected function addContextToMessages()
 71 |     {
 72 |         $context = $this->getContextMessage();
 73 | 
 74 |         if ($context === []) {
 75 |             return;
 76 |         }
 77 | 
 78 |         foreach ($this->messages as &$message) {
 79 |             $message[0] = ArrayHelper::merge($context, $this->parseText($message[0]));
 80 |         }
 81 |     }
 82 | 
 83 |     /**
 84 |      * Generates the context information to be logged.
 85 |      *
 86 |      * @return array
 87 |      */
 88 |     protected function getContextMessage()
 89 |     {
 90 |         $context = $this->context;
 91 | 
 92 |         if (($this->logUser === true) && ($user = \Yii::$app->get('user', false)) !== null) {
 93 |             /** @var \yii\web\User $user */
 94 |             $context['userId'] = $user->getId();
 95 |         }
 96 | 
 97 |         foreach ($this->logVars as $name) {
 98 |             if (empty($GLOBALS[$name]) === false) {
 99 |                 $context[$name] = & $GLOBALS[$name];
100 |             }
101 |         }
102 | 
103 |         return $context;
104 |     }
105 | 
106 |     /**
107 |      * Convert's any type of log message to array.
108 |      *
109 |      * @param mixed $text Input log message.
110 |      *
111 |      * @return array
112 |      */
113 |     protected function parseText($text)
114 |     {
115 |         $type = gettype($text);
116 |         switch ($type) {
117 |             case 'array':
118 |                 return $text;
119 |             case 'string':
120 |                 return ['@message' => $text];
121 |             case 'object':
122 |                 return get_object_vars($text);
123 |             default:
124 |                 return ['@message' => \Yii::t('log', "Warning, wrong log message type '{$type}'")];
125 |         }
126 |     }
127 | 
128 |     /**
129 |      * Transform log message to assoc.
130 |      *
131 |      * @param array $message The log message.
132 |      *
133 |      * @return array
134 |      */
135 |     protected function prepareMessage($message)
136 |     {
137 |         list($text, $level, $category, $timestamp) = $message;
138 | 
139 |         $level = Logger::getLevelName($level);
140 |         $timestamp = date('c', $timestamp);
141 | 
142 |         $result = ArrayHelper::merge(
143 |             $this->parseText($text),
144 |             ['level' => $level, 'category' => $category, '@timestamp' => $timestamp]
145 |         );
146 | 
147 |         if (isset($message[4]) === true) {
148 |             $result['trace'] = $message[4];
149 |         }
150 | 
151 |         return $result;
152 |     }
153 | }
154 | 


--------------------------------------------------------------------------------
/tests/_bootstrap.php:
--------------------------------------------------------------------------------
 1 | 
 5 |  * @license   https://raw.github.com/index0h/yii2-log/master/LICENSE
 6 |  */
 7 | 
 8 | defined('YII_DEBUG') or define('YII_DEBUG', true);
 9 | defined('YII_ENV') or define('YII_ENV', 'dev');
10 | 
11 | require_once __DIR__ . implode(DIRECTORY_SEPARATOR, ['', '..', 'vendor', 'autoload.php']);
12 | require_once __DIR__ . implode(DIRECTORY_SEPARATOR, ['', '..', 'vendor', 'yiisoft', 'yii2', 'Yii.php']);
13 | 
14 | Yii::setAlias('@tests', __DIR__);
15 | Yii::setAlias('@runtime', __DIR__ . DIRECTORY_SEPARATOR . '_runtime');
16 | 
17 | $configuration = require __DIR__ . DIRECTORY_SEPARATOR . 'unit' . DIRECTORY_SEPARATOR . '_config.php';
18 | 
19 | $application = new yii\console\Application($configuration);
20 | 


--------------------------------------------------------------------------------
/tests/_helpers/CodeHelper.php:
--------------------------------------------------------------------------------
  1 | 
  5 |  * @license   https://raw.github.com/index0h/yii2-log/master/LICENSE
  6 |  */
  7 | 
  8 | namespace Codeception\Module;
  9 | 
 10 | /**
 11 |  * @author Roman Levishchenko 
 12 |  */
 13 | class CodeHelper extends \Codeception\Module
 14 | {
 15 |     /** Alias to emergency log file. */
 16 |     const EMERGENCY_LOG = '@tests/_log/emergency.log';
 17 | 
 18 |     /** Alias to logstash log file. */
 19 |     const LOGSTASH_FILE_LOG = '@tests/_log/logstash.log';
 20 | 
 21 |     /** Redis log key. */
 22 |     const REDIS_LOG = 'yii_log';
 23 | 
 24 |     /**
 25 |      * @param string $message Message to log.
 26 |      */
 27 |     public function addElasticsearchLog($message)
 28 |     {
 29 |         $this->addLog($message, 'ElasticsearchTarget');
 30 |         sleep(1);
 31 |     }
 32 | 
 33 |     /**
 34 |      * @param string $message Message to log.
 35 |      * @param string $type    Type of message passed to logger.
 36 |      */
 37 |     public function addLogstashFileLog($message, $type)
 38 |     {
 39 |         switch ($type) {
 40 |             case 'array':
 41 |                 $message = ['@message' => $message];
 42 |                 break;
 43 |             case 'stdClass':
 44 |                 $tmp = new \stdClass();
 45 |                 $tmp->{'@message'} = $message;
 46 |                 $message = $tmp;
 47 |                 break;
 48 |         }
 49 |         \Yii::error($message, 'LogstashFileTarget');
 50 |         \Yii::getLogger()->flush(true);
 51 |     }
 52 | 
 53 |     /**
 54 |      * @param string $message Message to log.
 55 |      */
 56 |     public function addRedisLog($message)
 57 |     {
 58 |         $this->addLog($message, 'RedisTarget');
 59 |     }
 60 | 
 61 |     /**
 62 |      * @param string $message Message to log.
 63 |      */
 64 |     public function addWrongElasticsearchLog($message)
 65 |     {
 66 |         $this->addLog($message, 'WrongElasticsearchTarget');
 67 |     }
 68 | 
 69 |     /**
 70 |      * @param string $message Message to log.
 71 |      */
 72 |     public function addWrongLogstashLog($message)
 73 |     {
 74 |         $this->addLog($message, 'WrongLogstashTarget');
 75 |     }
 76 | 
 77 |     /**
 78 |      * @param string $message Message to log.
 79 |      */
 80 |     public function addWrongRedisLog($message)
 81 |     {
 82 |         $this->addLog($message, 'WrongRedisTarget');
 83 |     }
 84 | 
 85 |     public function dontSeeEmergencyLog()
 86 |     {
 87 |         $logFile = \Yii::getAlias(self::EMERGENCY_LOG);
 88 |         $this->assertFalse(file_exists($logFile));
 89 |     }
 90 | 
 91 |     public function flushElasticsearch()
 92 |     {
 93 |         $curl = curl_init('http://localhost:9200/yii');
 94 |         curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');
 95 |         curl_exec($curl);
 96 |         curl_close($curl);
 97 |     }
 98 | 
 99 |     public function flushRedis()
100 |     {
101 |         \Yii::$app->redis->flushall();
102 |     }
103 | 
104 |     public function removeEmergencyLog()
105 |     {
106 |         $logFile = \Yii::getAlias(self::EMERGENCY_LOG);
107 |         if (file_exists($logFile) === true) {
108 |             unlink($logFile);
109 |         }
110 |     }
111 | 
112 |     public function removeLogstashFile()
113 |     {
114 |         $logFile = \Yii::getAlias(self::LOGSTASH_FILE_LOG);
115 |         if (file_exists($logFile) === true) {
116 |             unlink($logFile);
117 |         }
118 |     }
119 | 
120 |     /**
121 |      * @param string $message Message to log.
122 |      */
123 |     public function seeElasticsearchLog($message)
124 |     {
125 |         $result = \Yii::$app->elasticsearch
126 |             ->createCommand(['index' => 'yii', 'type' => 'log'])
127 |             ->search([]);
128 |         $this->assertEquals($message, $result['hits']['hits'][0]['_source']['@message']);
129 |     }
130 | 
131 |     /**
132 |      * @param string $message Message to log.
133 |      */
134 |     public function seeEmergencyLog($message)
135 |     {
136 |         $content = file_get_contents(\Yii::getAlias(self::EMERGENCY_LOG));
137 |         $content = json_decode(trim($content), true);
138 | 
139 |         $this->assertEquals($content['@message'], $message);
140 |         $this->assertTrue(isset($content['emergency']));
141 |     }
142 | 
143 |     public function seeLogstashFile()
144 |     {
145 |         $logFile = \Yii::getAlias(self::LOGSTASH_FILE_LOG);
146 |         $this->assertTrue(file_exists($logFile));
147 |     }
148 | 
149 |     /**
150 |      * @param string $message Message to log.
151 |      */
152 |     public function seeRedisLog($message)
153 |     {
154 |         $this->assertEquals(1, \Yii::$app->redis->llen(self::REDIS_LOG));
155 | 
156 |         $log = json_decode(\Yii::$app->redis->lpop(self::REDIS_LOG), true);
157 | 
158 |         $this->assertEquals($message, $log['@message']);
159 |     }
160 | 
161 |     /**
162 |      * @param string|string[] $messages Message to log.
163 |      * @param string          $target   Name of log target.
164 |      */
165 |     protected function addLog($messages, $target)
166 |     {
167 |         if (gettype($messages) === 'string') {
168 |             $messages = [$messages];
169 |         }
170 |         foreach ($messages as $message) {
171 |             \Yii::error($message, $target);
172 |         }
173 | 
174 |         \Yii::getLogger()->flush(true);
175 |     }
176 | }
177 | 


--------------------------------------------------------------------------------
/tests/_log/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/index0h/yii2-log/a470a913e953a190880ced04ddfa13fe2ecc4811/tests/_log/.gitignore


--------------------------------------------------------------------------------
/tests/_runtime/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/index0h/yii2-log/a470a913e953a190880ced04ddfa13fe2ecc4811/tests/_runtime/.gitignore


--------------------------------------------------------------------------------
/tests/unit.suite.yml:
--------------------------------------------------------------------------------
1 | # Codeception Test Suite Configuration
2 | 
3 | # suite for unit (internal) tests.
4 | # RUN `build` COMMAND AFTER ADDING/REMOVING MODULES.
5 | 
6 | class_name: CodeGuy
7 | modules:
8 |     enabled: [CodeHelper]
9 | 


--------------------------------------------------------------------------------
/tests/unit/CodeGuy.php:
--------------------------------------------------------------------------------
  1 | scenario->runStep(new \Codeception\Step\Action('addElasticsearchLog', func_get_args()));
 36 |     }
 37 | 
 38 |  
 39 |     /**
 40 |      * [!] Method is generated. Documentation taken from corresponding module.
 41 |      *
 42 |      * @param string $message Message to log.
 43 |      * @param string $type    Type of message passed to logger.
 44 |      * @see \Codeception\Module\CodeHelper::addLogstashFileLog()
 45 |      */
 46 |     public function addLogstashFileLog($message, $type) {
 47 |         return $this->scenario->runStep(new \Codeception\Step\Action('addLogstashFileLog', func_get_args()));
 48 |     }
 49 | 
 50 |  
 51 |     /**
 52 |      * [!] Method is generated. Documentation taken from corresponding module.
 53 |      *
 54 |      * @param string $message Message to log.
 55 |      * @see \Codeception\Module\CodeHelper::addRedisLog()
 56 |      */
 57 |     public function addRedisLog($message) {
 58 |         return $this->scenario->runStep(new \Codeception\Step\Action('addRedisLog', func_get_args()));
 59 |     }
 60 | 
 61 |  
 62 |     /**
 63 |      * [!] Method is generated. Documentation taken from corresponding module.
 64 |      *
 65 |      * @param string $message Message to log.
 66 |      * @see \Codeception\Module\CodeHelper::addWrongElasticsearchLog()
 67 |      */
 68 |     public function addWrongElasticsearchLog($message) {
 69 |         return $this->scenario->runStep(new \Codeception\Step\Action('addWrongElasticsearchLog', func_get_args()));
 70 |     }
 71 | 
 72 |  
 73 |     /**
 74 |      * [!] Method is generated. Documentation taken from corresponding module.
 75 |      *
 76 |      * @param string $message Message to log.
 77 |      * @see \Codeception\Module\CodeHelper::addWrongLogstashLog()
 78 |      */
 79 |     public function addWrongLogstashLog($message) {
 80 |         return $this->scenario->runStep(new \Codeception\Step\Action('addWrongLogstashLog', func_get_args()));
 81 |     }
 82 | 
 83 |  
 84 |     /**
 85 |      * [!] Method is generated. Documentation taken from corresponding module.
 86 |      *
 87 |      * @param string $message Message to log.
 88 |      * @see \Codeception\Module\CodeHelper::addWrongRedisLog()
 89 |      */
 90 |     public function addWrongRedisLog($message) {
 91 |         return $this->scenario->runStep(new \Codeception\Step\Action('addWrongRedisLog', func_get_args()));
 92 |     }
 93 | 
 94 |  
 95 |     /**
 96 |      * [!] Method is generated. Documentation taken from corresponding module.
 97 |      *
 98 |      *
 99 |      * Conditional Assertion: Test won't be stopped on fail
100 |      * @see \Codeception\Module\CodeHelper::dontSeeEmergencyLog()
101 |      */
102 |     public function cantSeeEmergencyLog() {
103 |         return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeEmergencyLog', func_get_args()));
104 |     }
105 |     /**
106 |      * [!] Method is generated. Documentation taken from corresponding module.
107 |      *
108 |      *
109 |      * @see \Codeception\Module\CodeHelper::dontSeeEmergencyLog()
110 |      */
111 |     public function dontSeeEmergencyLog() {
112 |         return $this->scenario->runStep(new \Codeception\Step\Assertion('dontSeeEmergencyLog', func_get_args()));
113 |     }
114 | 
115 |  
116 |     /**
117 |      * [!] Method is generated. Documentation taken from corresponding module.
118 |      *
119 |      *
120 |      * @see \Codeception\Module\CodeHelper::flushElasticsearch()
121 |      */
122 |     public function flushElasticsearch() {
123 |         return $this->scenario->runStep(new \Codeception\Step\Action('flushElasticsearch', func_get_args()));
124 |     }
125 | 
126 |  
127 |     /**
128 |      * [!] Method is generated. Documentation taken from corresponding module.
129 |      *
130 |      *
131 |      * @see \Codeception\Module\CodeHelper::flushRedis()
132 |      */
133 |     public function flushRedis() {
134 |         return $this->scenario->runStep(new \Codeception\Step\Action('flushRedis', func_get_args()));
135 |     }
136 | 
137 |  
138 |     /**
139 |      * [!] Method is generated. Documentation taken from corresponding module.
140 |      *
141 |      *
142 |      * @see \Codeception\Module\CodeHelper::removeEmergencyLog()
143 |      */
144 |     public function removeEmergencyLog() {
145 |         return $this->scenario->runStep(new \Codeception\Step\Action('removeEmergencyLog', func_get_args()));
146 |     }
147 | 
148 |  
149 |     /**
150 |      * [!] Method is generated. Documentation taken from corresponding module.
151 |      *
152 |      *
153 |      * @see \Codeception\Module\CodeHelper::removeLogstashFile()
154 |      */
155 |     public function removeLogstashFile() {
156 |         return $this->scenario->runStep(new \Codeception\Step\Action('removeLogstashFile', func_get_args()));
157 |     }
158 | 
159 |  
160 |     /**
161 |      * [!] Method is generated. Documentation taken from corresponding module.
162 |      *
163 |      * @param string $message Message to log.
164 |      * Conditional Assertion: Test won't be stopped on fail
165 |      * @see \Codeception\Module\CodeHelper::seeElasticsearchLog()
166 |      */
167 |     public function canSeeElasticsearchLog($message) {
168 |         return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeElasticsearchLog', func_get_args()));
169 |     }
170 |     /**
171 |      * [!] Method is generated. Documentation taken from corresponding module.
172 |      *
173 |      * @param string $message Message to log.
174 |      * @see \Codeception\Module\CodeHelper::seeElasticsearchLog()
175 |      */
176 |     public function seeElasticsearchLog($message) {
177 |         return $this->scenario->runStep(new \Codeception\Step\Assertion('seeElasticsearchLog', func_get_args()));
178 |     }
179 | 
180 |  
181 |     /**
182 |      * [!] Method is generated. Documentation taken from corresponding module.
183 |      *
184 |      * @param string $message Message to log.
185 |      * Conditional Assertion: Test won't be stopped on fail
186 |      * @see \Codeception\Module\CodeHelper::seeEmergencyLog()
187 |      */
188 |     public function canSeeEmergencyLog($message) {
189 |         return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeEmergencyLog', func_get_args()));
190 |     }
191 |     /**
192 |      * [!] Method is generated. Documentation taken from corresponding module.
193 |      *
194 |      * @param string $message Message to log.
195 |      * @see \Codeception\Module\CodeHelper::seeEmergencyLog()
196 |      */
197 |     public function seeEmergencyLog($message) {
198 |         return $this->scenario->runStep(new \Codeception\Step\Assertion('seeEmergencyLog', func_get_args()));
199 |     }
200 | 
201 |  
202 |     /**
203 |      * [!] Method is generated. Documentation taken from corresponding module.
204 |      *
205 |      *
206 |      * Conditional Assertion: Test won't be stopped on fail
207 |      * @see \Codeception\Module\CodeHelper::seeLogstashFile()
208 |      */
209 |     public function canSeeLogstashFile() {
210 |         return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeLogstashFile', func_get_args()));
211 |     }
212 |     /**
213 |      * [!] Method is generated. Documentation taken from corresponding module.
214 |      *
215 |      *
216 |      * @see \Codeception\Module\CodeHelper::seeLogstashFile()
217 |      */
218 |     public function seeLogstashFile() {
219 |         return $this->scenario->runStep(new \Codeception\Step\Assertion('seeLogstashFile', func_get_args()));
220 |     }
221 | 
222 |  
223 |     /**
224 |      * [!] Method is generated. Documentation taken from corresponding module.
225 |      *
226 |      * @param string $message Message to log.
227 |      * Conditional Assertion: Test won't be stopped on fail
228 |      * @see \Codeception\Module\CodeHelper::seeRedisLog()
229 |      */
230 |     public function canSeeRedisLog($message) {
231 |         return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeRedisLog', func_get_args()));
232 |     }
233 |     /**
234 |      * [!] Method is generated. Documentation taken from corresponding module.
235 |      *
236 |      * @param string $message Message to log.
237 |      * @see \Codeception\Module\CodeHelper::seeRedisLog()
238 |      */
239 |     public function seeRedisLog($message) {
240 |         return $this->scenario->runStep(new \Codeception\Step\Assertion('seeRedisLog', func_get_args()));
241 |     }
242 | }
243 | 


--------------------------------------------------------------------------------
/tests/unit/ElasticsearchCest.php:
--------------------------------------------------------------------------------
 1 | 
 5 |  * @license   https://raw.github.com/index0h/yii2-log/master/LICENSE
 6 |  */
 7 | 
 8 | /**
 9 |  * Check ElasticsearchTarget.
10 |  *
11 |  * @author Roman Levishchenko 
12 |  */
13 | class ElasticsearchCest
14 | {
15 |     public function addCorrectElasticsearchLog(\CodeGuy $I, \Codeception\Scenario $scenario)
16 |     {
17 |         if ($scenario->running() === false) {
18 |             return;
19 |         }
20 |         $I->removeEmergencyLog();
21 |         $I->flushElasticsearch();
22 | 
23 |         $I->addElasticsearchLog('CorrectLog');
24 |         $I->dontSeeEmergencyLog();
25 |         $I->seeElasticsearchLog('CorrectLog');
26 |     }
27 | 
28 |     public function addWrongElasticsearchLog(\CodeGuy $I, \Codeception\Scenario $scenario)
29 |     {
30 |         if ($scenario->running() === false) {
31 |             return;
32 |         }
33 |         $I->removeEmergencyLog();
34 |         $I->flushElasticsearch();
35 |         $I->addWrongElasticsearchLog('WrongElasticsearchLog');
36 |         $I->seeEmergencyLog('WrongElasticsearchLog');
37 |     }
38 | }
39 | 


--------------------------------------------------------------------------------
/tests/unit/LogstashCest.php:
--------------------------------------------------------------------------------
 1 | 
 5 |  * @license   https://raw.github.com/index0h/yii2-log/master/LICENSE
 6 |  */
 7 | 
 8 | /**
 9 |  * Check LogstashTarget.
10 |  *
11 |  * @author Roman Levishchenko 
12 |  */
13 | class LogstashCest
14 | {
15 | 
16 |     public function addWrongLogstashLog(\CodeGuy $I, \Codeception\Scenario $scenario)
17 |     {
18 |         if ($scenario->running() === false) {
19 |             return;
20 |         }
21 |         $I->removeEmergencyLog();
22 |         $I->addWrongLogstashLog('WrongLogstashLog');
23 |         $I->seeEmergencyLog('WrongLogstashLog');
24 |     }
25 | }


--------------------------------------------------------------------------------
/tests/unit/LogstashFileCest.php:
--------------------------------------------------------------------------------
 1 | 
 5 |  * @license   https://raw.github.com/index0h/yii2-log/master/LICENSE
 6 |  */
 7 | 
 8 | /**
 9 |  * Check LogstashFileTarget.
10 |  *
11 |  * @author Roman Levishchenko 
12 |  */
13 | class LogstashFileCest
14 | {
15 |     public function addLogstashLogToFile(\CodeGuy $I, \Codeception\Scenario $scenario)
16 |     {
17 |         if ($scenario->running() === false) {
18 |             return;
19 |         }
20 |         $I->removeLogstashFile();
21 |         $I->addLogstashFileLog('logstashFileLog_array', 'array');
22 |         $I->addLogstashFileLog('logstashFileLog_stdClass', 'stdClass');
23 |         $I->seeLogstashFile();
24 |     }
25 | }


--------------------------------------------------------------------------------
/tests/unit/RedisCest.php:
--------------------------------------------------------------------------------
 1 | 
 5 |  * @license   https://raw.github.com/index0h/yii2-log/master/LICENSE
 6 |  */
 7 | 
 8 | /**
 9 |  * Check RedisTarget.
10 |  *
11 |  * @author Roman Levishchenko 
12 |  */
13 | class RedisCest
14 | {
15 |     public function addCorrectRedisLog(\CodeGuy $I, \Codeception\Scenario $scenario)
16 |     {
17 |         if ($scenario->running() === false) {
18 |             return;
19 |         }
20 |         $I->removeEmergencyLog();
21 |         $I->flushRedis();
22 |         $I->addRedisLog('CorrectLog');
23 |         $I->dontSeeEmergencyLog();
24 |         $I->seeRedisLog('CorrectLog');
25 |     }
26 | 
27 |     public function addWrongRedisLog(\CodeGuy $I, \Codeception\Scenario $scenario)
28 |     {
29 |         if ($scenario->running() === false) {
30 |             return;
31 |         }
32 |         $I->removeEmergencyLog();
33 |         $I->flushRedis();
34 |         $I->addWrongRedisLog('WrongRedisLog');
35 |         $I->seeEmergencyLog('WrongRedisLog');
36 |     }
37 | }
38 | 


--------------------------------------------------------------------------------
/tests/unit/_bootstrap.php:
--------------------------------------------------------------------------------
1 | 
5 |  * @license   https://raw.github.com/index0h/yii2-log/master/LICENSE
6 |  */
7 | 


--------------------------------------------------------------------------------
/tests/unit/_config.php:
--------------------------------------------------------------------------------
 1 | 
 5 |  * @license   https://raw.github.com/index0h/yii2-log/master/LICENSE
 6 |  */
 7 | 
 8 | return [
 9 |     'id' => 'basic',
10 |     'basePath' => \Yii::getAlias('@tests'),
11 |     'runtimePath' => \Yii::getAlias('@tests/_runtime'),
12 |     'bootstrap' => ['log'],
13 |     'components' => [
14 |         'redis' => ['class' => 'yii\redis\Connection'],
15 |         'elasticsearch' => ['class' => 'yii\elasticsearch\Connection'],
16 |         'log' => [
17 |             'traceLevel' => 3,
18 |             'targets' => [
19 |                 [
20 |                     'class' => 'index0h\\log\\ElasticsearchTarget',
21 |                     'categories' => ['ElasticsearchTarget'],
22 |                     'emergencyLogFile' => '@tests/_log/emergency.log'
23 |                 ],
24 |                 [
25 |                     'class' => 'index0h\\log\\ElasticsearchTarget',
26 |                     'categories' => ['WrongElasticsearchTarget'],
27 |                     'componentName' => 'WRONG',
28 |                     'emergencyLogFile' => '@tests/_log/emergency.log'
29 |                 ],
30 |                 [
31 |                     'class' => 'index0h\\log\\LogstashFileTarget',
32 |                     'categories' => ['LogstashFileTarget'],
33 |                     'logFile' => '@tests/_log/logstash.log'
34 |                 ],
35 |                 [
36 |                     // Travis doesn't have logstash implementation.
37 |                     'class' => 'index0h\\log\\LogstashTarget',
38 |                     'categories' => ['WrongLogstashTarget'],
39 |                     'dsn' => 'tcp://WRONG_HOST:12045',
40 |                     'emergencyLogFile' => '@tests/_log/emergency.log'
41 |                 ],
42 |                 [
43 |                     'class' => 'index0h\\log\\RedisTarget',
44 |                     'categories' => ['RedisTarget'],
45 |                     'emergencyLogFile' => '@tests/_log/emergency.log',
46 |                     'key' => 'yii_log'
47 |                 ],
48 |                 [
49 |                     'class' => 'index0h\\log\\RedisTarget',
50 |                     'categories' => ['WrongRedisTarget'],
51 |                     'componentName' => 'WRONG',
52 |                     'emergencyLogFile' => '@tests/_log/emergency.log'
53 |                 ],
54 |             ],
55 |         ],
56 |     ]
57 | ];


--------------------------------------------------------------------------------