DataGridView上のデータを絞り込み表示する
DataGridViewに表示されているデータに対して、絞り込み条件を指定し表示させたい場合は BindingSourceクラスのFilterプロパティが使用できる。
BindingSource.Filter プロパティ (System.Windows.Forms)
手順
- DataGridViewにバインドしたDataSourceをDataTableとして取得する。
- DataTableをBindingSource.DataSourceプロパティにセットする。
- BindingSource.Filterプロパティに絞り込み条件を設定する。
- Filterに設定した条件で絞り込みされた結果がDataGridViewに表示される。
フォーム上のテキストボックスに入力された値がDataGridViewに対しての絞り込み条件としたとき、 TextChangedイベントが発生するたびにフィルター処理を呼ぶようにハンドラを追加する。 見かけ上分かりやすかったのでTextChangedをイベントに指定しているが、このイベント自体は別に何でも良い。
''' ロード時の初期設定 Private Sub Form_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load ' テキストボックスに変更があった場合のイベントハンドラを追加する AddHandler txt_Condition.TextChanged, AddressOf DataGridViewFilter End Sub
テキストボックスがTextChangedイベントを発生するたびに呼び出される関数上で、 絞り込み条件の記述を整形し、BindingSourceにデータと絞り込み条件を設定する。
Private Sub DataGridViewFilter() Dim objBind As BindingSource Dim objData As DataTable Dim strFilter As String ' DataGridViewにバインドしたデータをDataTableとして取得する objData = CType(DataGridView1.DataSource, DataTable) ' データが存在する場合 If IsNothing(objData) = False Then objBind = New BindingSource ' バインドするデータソースにDataTableをセット objBind.DataSource = objData ' DataGridViewの表示内容を絞り込むための条件式を設定する strFilter = "Color like '%" & txt_Condition.Text & "%'" ' データソースにフィルターをセット objBind.Filter = strFilter End If End Sub
DataGridViewが以下の状態で表示されている場合、
Seq | Month | Day | Color |
---|---|---|---|
1 | 8 | 1 | Orange |
2 | 4 | 17 | Blue |
3 | 9 | 19 | Light Pink |
4 | 3 | 4 | Yellow |
5 | 9 | 21 | Pink |
6 | 7 | 13 | White |
7 | 1 | 1 | Red |
8 | 2 | 10 | Green |
9 | 6 | 13 | Purple |
テキストボックスにPink
と入力があった場合、DataGridViewに対する絞り込み条件はColor like '%Pink%'
となる。
あとはこの条件式をBindingSourceにセットすることでDataGridViewの表示状態は以下のように変更される。
Seq | Month | Day | Color |
---|---|---|---|
3 | 9 | 19 | Light Pink |
5 | 9 | 21 | Pink |
記述した内容だと入力の都度TextChangedイベントが発生してしまう。
絞り込みの条件句を部分一致にしているので、P
と入力した時点でTextChangedイベントが発生し、
Light Pink
、Pink
、Purple
の3件が表示される。
このあたりの振る舞いは別のイベントで制御するほうがスマートかもしれない。*1
この記事は今度書き直す。
*1:とはいえEnterキーとか検索ボタンをトリガーにしたくないという要望があってこのまま実装した。
ヤマハRTX1200から出力したログをLogstashを使用してelasticsearchに登録、Kibanaで可視化してみた
ヤマハRTX1200のsyslogにURLフィルターのログを出力するようにしています。 このURLフィルターのログをLogstashを使用してelasticsearchに登録し、kibanaで可視化してみました。
使用するログ
syslog全体から以下のログを抜き出しテストで使用しました。
2018/02/08 00:50:07: [SD] Logfile is opened("sd1:rt_syslog.log", maximum size: 455524352 bytes) 2018/02/08 00:50:32: [URL_FILTER] Passed at LAN1 IN(2) filter: 192.168.1.2 : http://www.hatena.ne.jp/ 2018/02/08 00:50:32: [URL_FILTER] Passed at LAN1 OUT(1) filter: 192.168.1.2 : http://www.hatena.ne.jp/ 2018/02/08 01:03:39: [URL_FILTER] Passed at LAN1 IN(2) filter: 192.168.1.2 : http://weathernews.jp/pinpoint/cgi/search_result.fcgi?service=11&lat=&lon=&ameno=67437&name=広島&pref=67 2018/02/08 01:03:39: [URL_FILTER] Passed at LAN1 OUT(1) filter: 192.168.1.2 : http://weathernews.jp/pinpoint/cgi/search_result.fcgi?service=11&lat=&lon=&ameno=67437&name=広島&pref=67 2018/02/13 19:43:51: LAN1: PORT8 link down 2018/02/13 19:43:53: LAN1: PORT8 link up (10BASE-T Full Duplex) 2018/02/13 19:44:33: LAN1: PORT8 link down 2018/02/13 19:44:35: LAN1: PORT8 link up (1000BASE-T Full Duplex) 2018/02/12 17:36:34: [URL_FILTER] Passed at LAN1 IN(2) filter: 192.168.1.2 : http://b.hatena.ne.jp/js/hatena_dfp2.js 2018/02/12 17:36:34: [URL_FILTER] Passed at LAN1 OUT(1) filter: 192.168.1.2 : http://b.hatena.ne.jp/js/hatena_dfp2.js 2018/02/14 19:10:32: [EXTMEMBOOT] Configuration file was not found. 2018/02/14 19:10:32: [EXTMEMBOOT] Firmware file was not found. 2018/02/15 01:14:05: [URL_FILTER] Passed at LAN1 IN(2) filter: 192.168.1.2 : http://www.yahoo.co.jp/ 2018/02/15 01:14:05: [URL_FILTER] Passed at LAN1 OUT(1) filter: 192.168.1.2 : http://www.yahoo.co.jp/ 2018/02/15 01:18:23: [URL_FILTER] Passed at LAN1 IN(2) filter: 192.168.1.2 : http://hatenablog.com/?via=201002 2018/02/15 01:18:23: [URL_FILTER] Passed at LAN1 OUT(1) filter: 192.168.1.2 : http://hatenablog.com/?via=201002
Grokフィルターパターンの作成
このログをGrokフィルターで項目ごとにパースします。
ログの中でYYYY/MM/DD HH:MM:SS: [URL_FILTER]...
からはじまるデータのみ対象になるようフィルターパターンを作成します。
Grokのパターンは以下を参照しました。 logstash-patterns-core/grok-patterns at master · logstash-plugins/logstash-patterns-core · GitHub
フィルターパターンはGrok Debuggerを使用しながら作成しました。 Grok Debuggerは入力したいログとパターンを入力することでテストしながら作成ができて便利です。
今回は以下のようなフィルターパターンを作成しました。*1
%{YEAR:year}/%{MONTHNUM:month}/%{MONTHDAY:day}\s%{HOUR:hour}:%{MINUTE:min}:%{SECOND:sec}:\s*\[URL_FILTER\]\s*Passed\s*at\s*LAN%{INT:lan}\s*%{WORD:inout}\(%{INT:filter}\)\s*filter:\s*%{IP:clientip}\s*:\s*%{URIPROTO:uriproto}://(?:%{USER:user}(?::[^@]*)?@)?(?:%{URIHOST:urihost})?(?:%{URIPATHPARAM:uriparam})
Logstashの設定・起動
作成したフィルターパターンをlogstash/conf.d/pipeline.conf
に記述します。
$ sudo /etc/logstash/conf.d/pipeline.conf
ログファイルは先頭から読み込みます。 テストなのでインデックスも特に指定していません。
input { file { path => "/home/urlFilter.log" start_position => "beginning" } } filter{ grok { match => ["message", "%{YEAR:year}/%{MONTHNUM:month}/%{MONTHDAY:day}\s%{HOUR:hour}:%{MINUTE:min}:%{SECOND:sec}:\s*\[URL_FILTER\]\s*Passed\s*at\s*LAN%{INT:lan}\s*%{WORD:inout}\(%{INT:filter}\)\s*filter:\s*%{IP:clientip}\s*:\s*%{URIPROTO:uriproto}://(?:%{USER:user}(?::[^@]*)?@)?(?:%{URIHOST:urihost})?(?:%{URIPATHPARAM:uriparam})"] } } output { elasticsearch { hosts => ["localhost:9200"] } }
Logstashを起動しelasticsearchにデータを登録します。
$ sudo service logstash start
elasticsearchの確認
elasticsearchにデータが登録されているか見てみます。
$ curl -XGET localhost:9200/_cat/indices?v
テストで使用したログ17行が取り込まれています。
インデックスは指定しなかったのでlogstash-2018.02.17
で作成されています。
$ curl -XGET localhost:9200/_cat/indices?v health status index uuid pri rep docs.count docs.deleted store.size pri.store.size yellow open .kibana 9fT-tqMkRfq0mG30uGXBug 1 1 1 0 3.2kb 3.2kb yellow open logstash-2018.02.17 lvliGqYrSV6GFuVyW2DKcQ 5 1 17 0 57.5kb 57.5kb
kibanaで可視化
kibanaで取り込んだデータを見てみます。 Discoverでelasticsearchにデータを取り込んだ時間ごとの件数と生のデータを見ることができます。
取り込んだデータを選択するとGrokフィルターに記述した通りにデータがパースされている事が確認できます。
Grokフィルターでパース出来なかったデータについては、tagsに_grokparsefailure
と記述されています。
取り込んだテストデータの1行目、6~9行目、12、13行目が該当していました。
取り込んだデータが想定通りにパースされていたのでVisualizeで可視化してみます。 Pieチャートでデータを見てみたところ、初期状態では取り込んだ全17件がCountで表示されています。
urlhost単位で件数を見るため、buckets項目でSplit Slicesを選択し、AggregationでTerms、Fieldでurlhost.keywordを選択します。 設定後、Apply Changes(▷ボタン)をクリックするとチャートが分割されます。 ここでチャート内にカーソルを当てると各データのカウントを見ることが出来ます。
このとき、テストで使用したデータの17件のうち7件はGrokフィルターに当てはまらなかったデータになるのでチャートの対象は10件になります。
逆にTermsでtags.keywordを選択すると、10件のデータにはtagsに値が無いので_grokparsefailure
の7件が結果として表示されます。
同じ要領でVisualizeからData Tableを選択します。 Split RowsでAggregationでTerms、Fieldでurlhost.keywordを選択すると各データの件数が表示されます。
Visualizeは画面右上のSaveから設定を保存することができます。
さらにデータを取り込んだ結果
Grokフィルターでデータをパースできることを確認できたので、とりあえず手元にあるデータ150000件を登録してみました。 パッと見た感じやはりというか広告、CDNと思われる場所とのアクセス数が多い気がします。
Pieチャートとは別にVertical Barで日ごとのアクセス先が可視化できるようにしました。*2 Kibanaの運用は当面これでやっていこうと思います。
データ分析基盤構築入門[Fluentd、Elasticsearch、Kibanaによるログ収集と可視化]
- 作者: 鈴木健太,吉田健太郎,大谷純,道井俊介
- 出版社/メーカー: 技術評論社
- 発売日: 2017/09/21
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (2件) を見る
*1:syslogで対象としたいログはこれだけではないので、フィルターはGistで更新していく。https://gist.github.com/mamori017/14b3ea1b809a797042bb0232214e4a52
Elasticsearchをアップデートしたら起動できなくなったのでKuromojiプラグインを再インストールした
Ubuntuのパッケージを更新したところ、ElasticsearchとKibanaのバージョンが5.6.7にアップデートされていました。 OS再起動ののちElasticsearchとKibanaの起動状態を見てみたところElasticsearchだけ起動していません。
$ sudo service --status-all | grep -e "elastic" -e "kibana" [ - ] elasticsearch [ + ] kibana
以前、Elasticsearchを5.0.0から5.4.0にアップデートした時、Kuromojiプラグインがバージョン非対応になり起動できなくなった経緯*1があります。恐らく同事象だと思いElasticsearchのログ(/var/log/elasticsearch/elasticesarch.log
)を見たところ、やはりKuromojiプラグインのバージョンが原因のようです。
[2018-02-06T23:49:32,824][ERROR][o.e.b.Bootstrap ] Exception java.lang.IllegalArgumentException: plugin [analysis-kuromoji] is incompatible with version [5.6.7]; was designed for version [5.4.0] at org.elasticsearch.plugins.PluginInfo.readFromProperties(PluginInfo.java:146) ~[elasticsearch-5.6.7.jar:5.6.7] at org.elasticsearch.bootstrap.Spawner.spawnNativePluginControllers(Spawner.java:80) ~[elasticsearch-5.6.7.jar:5.6.7] at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:168) ~[elasticsearch-5.6.7.jar:5.6.7] at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:342) [elasticsearch-5.6.7.jar:5.6.7] at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:132) [elasticsearch-5.6.7.jar:5.6.7] at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:123) [elasticsearch-5.6.7.jar:5.6.7] at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:70) [elasticsearch-5.6.7.jar:5.6.7] at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:134) [elasticsearch-5.6.7.jar:5.6.7] at org.elasticsearch.cli.Command.main(Command.java:90) [elasticsearch-5.6.7.jar:5.6.7] at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:91) [elasticsearch-5.6.7.jar:5.6.7] at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:84) [elasticsearch-5.6.7.jar:5.6.7] [2018-02-06T23:49:32,845][WARN ][o.e.b.ElasticsearchUncaughtExceptionHandler] [] uncaught exception in thread [main] org.elasticsearch.bootstrap.StartupException: java.lang.IllegalArgumentException: plugin [analysis-kuromoji] is incompatible with version [5.6.7]; was designed for version [5.4.0] at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:136) ~[elasticsearch-5.6.7.jar:5.6.7] at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:123) ~[elasticsearch-http://blog.hatena.ne.jp/mamori017/mamori017.hatenablog.com/edit#5.6.7.jar:5.6.7] at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:70) ~[elasticsearch-5.6.7.jar:5.6.7] at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:134) ~[elasticsearch-5.6.7.jar:5.6.7] at org.elasticsearch.cli.Command.main(Command.java:90) ~[elasticsearch-5.6.7.jar:5.6.7] at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:91) ~[elasticsearch-5.6.7.jar:5.6.7] at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:84) ~[elasticsearch-5.6.7.jar:5.6.7] Caused by: java.lang.IllegalArgumentException: plugin [analysis-kuromoji] is incompatible with version [5.6.7]; was designed for version [5.4.0] at org.elasticsearch.plugins.PluginInfo.readFromProperties(PluginInfo.java:146) ~[elasticsearch-5.6.7.jar:5.6.7] at org.elasticsearch.bootstrap.Spawner.spawnNativePluginControllers(Spawner.java:80) ~[elasticsearch-5.6.7.jar:5.6.7] at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:168) ~[elasticsearch-5.6.7.jar:5.6.7] at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:342) ~[elasticsearch-5.6.7.jar:5.6.7] at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:132) ~[elasticsearch-5.6.7.jar:5.6.7] ... 6 more
ログにはインストールされているKuromojiプラグインはElasticsearch 5.4.0用で、 5.6.7は非対応と書かれているのでプラグインを手動で更新します。 プラグインを上書きインストールをしようとするとエラーになったので一旦削除ののち再インストールします。
# 削除 $ sudo /usr/share/elasticsearch/bin/elasticsearch-plugin remove analysis-kuromoji # インストール $ sudo /usr/share/elasticsearch/bin/elasticsearch-plugin install analysis-kuromoji
Kuromojiプラグインを再インストール後、Elasticsearchを手動起動したところサービスが立ち上がるようになりました。
$ sudo /etc/init.d/elasticsearch start [ ok ] Starting elasticsearch (via systemctl): elasticsearch.service. $ sudo service --status-all | grep "elastic" [ + ] elasticsearch
データ分析基盤構築入門[Fluentd、Elasticsearch、Kibanaによるログ収集と可視化]
- 作者: 鈴木健太,吉田健太郎,大谷純,道井俊介
- 出版社/メーカー: 技術評論社
- 発売日: 2017/09/21
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (2件) を見る
*1:2017/5/7、5.0.0->5.4.0アップデート時に同様の記事を書いていたので削除した。