fluentdのHTTP OUTPUTって、意外と使われてないのか、

マニュアルを見たのですが、ちょっと引っかかったので、

備忘録がてら設定晒そうかと。

(fluentd http out の公式マニュアル)

https://docs.fluentd.org/output/http


とりあえず、設定です。

なおバージョンは、1.16.2です。

<source>
  @type forward
  port 24224
</source>
<match **>
  @type http
  endpoint http://host.docker.internal:8080/Store/${tag}
  http_method post 
  json_array false
  open_timeout 3
  read_timeout 3
  retryable_response_codes [503]
  <format>
    @type json
  </format>
  <buffer tag>
    @type file
    path /fluentd/log/transfer/buffer/
    chunk_limit_size 1m
    retry_wait 10s
    retry_max_times 3
    flush_mode interval
    flush_interval 1m
    flush_at_shutdown true
  </buffer>
</match>

endpointに${tag}という変数を使う場合、

bufferに書かないといけないというのがまずつまりました。(必須というのがわからんかった)

あとは、endpointに環境変数とかも使えるのかと思いきや、どうやら使えないようで、

このあたりも同時にハマったポイントでした。

その他、いつのバージョンからか、bufferの書き方もかなり変わっており、

このあたりもマニュアル見つつ、動かしながら確認しました。

fluentdはバージョンアップすると、結構書き方が変わっていたり、

パラメータが変更になっていたりと、なかなか注意が必要です。

とはいえ、相変わらず重宝しているfluentdです。

ちなみに、個人的に作成しているFluentNettingなんてものもあります。

https://www.nuget.org/packages/FluentNetting/

こいつはFORWARD OUPUTを受信するサーバですが、

ヘルスチェックなんかも持っているので、おすすめです。

以上

投稿日時:2024年02月14日 23:51   カテゴリー:fluentd  

ebonyrack 0.5.2 のリリースとともに、日本語マニュアルを追加しました。

(リリース)

https://github.com/shigenobu/ebonyrack/releases

(マニュアル)

https://github.com/shigenobu/ebonyrack/blob/master/manual/manual.ja.md

これでかなりわかりやすくなったと思うので、

利用者が増えてくれると嬉しいと思っていたりする自分がいます。。


0.5.2 では大掛かりな変更はないのですが、

HTML出力で、これまで<map><area>タグで制御していた部分を、

<svg><rect>タグで制御するように変更しました。

なぜ、svgを採用したかというと、mapだとクリックした場所を目立たせるというようなことが難しく、

そこでsvgとすることでクリックした場所を目立たせるようにすることが可能となりました。

<img usemap="#components" id="image" src="data:image/png;base64,..."/>
<map name="components">
  <area id="a" shape="rect" coords="10,10,20,20"/>
  <area id="b" shape="rect" coords="20,20,30,30"/>
  <area id="c" shape="rect" coords="30,30,40,40"/>
</map>
<script type="text/javascript">
var es = document.querySelectorAll("area");
for (let i = 0; i < es.length; i++) {
  es[i].addEventListener('click', (e) => {
    // ダイアログを表示する処理
  });
}
</script>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
  <image href="data:image/png;base64,..." width="100" height="100"/>
  <rect id="a" x="10" y="10" width="10" height="10" fill="red" fill-opacity="0" stroke="red" stroke-opacity="0"/>
  <rect id="b" x="20" y="20" width="10" height="10" fill="red" fill-opacity="0" stroke="red" stroke-opacity="0"/>
  <rect id="c" x="30" y="30" width="10" height="10" fill="red" fill-opacity="0" stroke="red" stroke-opacity="0"/>
</svg>
<script type="text/javascript">
var es = document.querySelectorAll("rect");
for (let i = 0; i < es.length; i++) {
  es[i].addEventListener('click', (e) => {
    // opacityの操作(他のrectのopacityを戻す操作は割愛)
    es[i].setAttribute("fill-opacity", "0.2");
    es[i].setAttribute("stroke-opacity", "1");
  
    // ダイアログを表示する処理
  });
}
</script>

見ていただければわかるかと思うのですが、

svgでrectを作っておき、不可視状態(opacityを0)にしておき、

クリックイベントで可視状態(opacityを0以外)にするというものです。

mapだと、areaのどこをクリックしたのかわかりずらかったものが、

svgとrectを使うことでクリックした場所(対応するオブジェクト)をわかりやすく表示できるようになります。

イメージを添付しておきます。

(初期状態)

(クリック後)※ダイアログが立ち上がっていますが、赤くなっていることがわかるかと。

意外とこういうことをコードレベルでやっている人は少ないようで、

svgの仕様見ながら試行錯誤で書いてみました。

今後は、積極的にsvgを活用するのもありだなと思っています。

以上

投稿日時:2024年02月14日 23:36   カテゴリー:html, java, mariadb, mysql  

ebonyrack 0.5.0 をリリースしました。(最近こればかり。。)

https://github.com/shigenobu/ebonyrack/releases

0.4.0 から 0.5.0 での機能追加は以下のとおりです。

  • テーブルからクラス作成(一括・個別)
  • DDLインポートの個別対応
  • テーブル・シーケンス・ノートのコピー&ペイスト
  • DDLに関連するノートの情報をdocコメントとして記載

その他、諸々細かな修正等はありますが、

今回の中では「テーブルからクラス作成」が比較的大きな機能かなと。

これはテンプレートにテーブル情報を渡して、

そのテンプレートをレンダリングすることでクラス(ソースコード)の生成が出来るというものです。

テンプレートは、Velocityの機能が使えるので、他テンプレートを取り込んだりすることもできます。

テンプレートはカスタマイズ可能です。

テンプレートは、

~/.ebonyrack/template/

ディレクトリ以下に配備します。起動時にサンプルが配備されます。

「Sample.java.vm」というように、「{識別名}.{出力したい拡張子}.vm」としてください。

「コピー&ペイスト」もかなり大変ではあったのですが、ひとまずできてます。

とはいえ、コピー時に参照をコピーするだけで、ペイスト時に複製をかける仕組みにしているため、

コピーからペイストの間に、元データに修正が入ると、ペイストされたデータも同様の変更が入るようになってます。

そもそも、コピー&ペイストとして、これがあっているかはわからないのですが、

ひとまずそんな感じになってます。

だいぶできたのですが、少し忙しくなりそうなので、

ebonyrackの機能追加は見合わせようかなと。

もちろん、不具合あれば修正していきますが、

時間みて、操作マニュアル等のドキュメント作成をしていこうかと考えています。

改めて、0.5.0 での機能は以下のようになってます。

  • テーブル作成
  • シーケンス作成
  • ノート作成
  • データのWrite out → JSONを出力するので、バージョン管理で使えるかも
  • データのRead in → Write outされたJSONを取り込めるので、作業者以外はいいかも
  • DDLのImport(最初に一括と、個別で追加)
  • DDLの出力(一括と個別)
  • 画像の出力
  • HTMLの出力 → 本アプリを使わない作業者にいいかも
  • クラス用ソースコード生成(一括と個別)

機能としては、一通り出揃った感はあるので、

今後としては、使い勝手の向上、見栄えの向上、パフォーマンス調整とかでしょうか。

使ってくれる人がいれば嬉しいです。

以上

投稿日時:2024年01月26日 16:19   カテゴリー:java, mariadb, mysql  

ebonyrack 0.4.0 をリリースしました。

https://github.com/shigenobu/ebonyrack/releases

今回の目玉は、DDLからのIMPORTです。

結構危険な機能なので、新規プロジェクト作成直後しか利用できません。

この機能により、mysqldumpまたはmariadb-dumpで出力される

  • CREATE SEQUENCE
  • CREATE TABLE

をパースして、ebonyrack上に展開することが可能となります。

いい加減なDDLでは駄目で、データベースが吐き出すDDLを使ってください。

こんな感じですね。

mariadb-dump --databases test -d > test.sql

DDLのパースには、antlr4を使っています。

(ANTLR)

https://www.antlr.org/

※内包したため、かなりバイナリが重くなりました。。

※ANTLRを使ったMariaDBのパースについては、そのうち書こうかと思います。

とはいえ、以下の機能の部分のパースは無視しています。

  • テーブルのオプション
  • カラムのオプション(生成列とかCHECK制約とかINVISIBLEとか)
  • 外部キー

一応、実案件の100を超えるテーブルは取り込めたので、まあ大丈夫かなと。

備忘録を兼ねて、今後のTODOを記載しておきます。

  • オブジェクトのコピー&ペイスト(やっぱりあるといいなと思いました)
  • IE記法の導入
  • ヘルプダイアログ
  • クラス生成
  • DDL出力時に関連するノートをDOCコメントとして出力

このうちの「クラス生成」は、テンプレートを指定すると、

クラスコードが作れるってやつですね。

これをやると、設計段階でプログラムのクラスが作成できるのでいいかなと思っています。

以上

投稿日時:2024年01月19日 16:30   カテゴリー:java, mariadb, mysql  

https://github.com/shigenobu/ebonyrack/releases

というわけで、今月は滅茶苦茶バージョンアップしました。

ERMASTERの代替を目指して作り始めてみましたが、

逆にERMASTERの偉大さを痛感しています。。

代替なんておこがましいですね。。

とはいえ、機能紹介をしておきます。


  • テーブル作成
  • シーケンス作成
  • ノート作成
  • データのWrite out → JSONを出力するので、バージョン管理で使えるかも
  • データのRead in → Write outされたJSONを取り込めるので、作業者以外はいいかも
  • DDLの出力
  • 画像の出力
  • HTMLの出力 → 本アプリを使わない作業者にいいかも

って具合です。

細かい不具合(わかっている限り描画の背景が一部無くなるとか、画像出力がまれにおかしくなるとか)やら(0.3.5で修正しました、多分)、

どうしてもチェックしきれいないところ(check制約やpartitionの式部分の正当性の保証ができない)もありますが、

かなり使えるレベルまで進化したかと自己満足しています。

あとは、どのくらいのオブジェクト数に耐えられるかを試験したいのですが、

そうなると、実案件からインポートするような機能が必要となり、

今のアプリとは別に作ることも考えています。(Read inがあるから別につくっても行けそうな気がする)

とはいえ、アプリではカラム情報なんかは「辞書」という形で持っていたり、

外部キー制約を厳し目にやっていたりするので、インポートも一筋縄ではいかなそうです。

ヘルプというかマニュアルというかも整備しないと意味が不明なので、

操作性の修正に加えて、インポートやらヘルプなんかも少しずつ進められばと考えています。

以上

投稿日時:2023年12月12日 16:52   カテゴリー:java, mariadb, mysql  

掲題のものを実装してみました。

https://github.com/shigenobu/PurpleSofa

もともと、クライアントは1接続前提で作っていたのですが、

TCPのプロキシサーバーを作りたいなーと思い、

ベースライブラリとして、上記ライブラリに複数クライアントを束ねる機能を作ってみました。

PurpleSofaの特徴の1つとして、TCPセッションの最終受信時刻からアイドルタイムを経過すると、

TCPセションを強制的に切断するようにしています。

これはハーフCLOSE対策のためです。

サーバ側は、複数のTCPセッションをまとめて管理していたいのですが、

今回クライアント側も同じ様な対応を施しました。

で、そもそもとしてはTCPプロキシサーバーを作りたいというところなのですが、

長年お世話になっていたHAPROXYが、2系でコンテナで動かすと異常にCPUを消費するということがあり、

公式のISSUEでもあがっているのですが、なかなか完全対応というわけにはいかなそうです。

1系は問題ないので、仕事では1系を使ってますが、、もう古いので。。

意外なほどに、HAPROXYのようなヘルスチェックを兼ねているプロキシサーバーというものは少なく、

K8Sとかの大規模向けだと、どうも取り回しが悪いので、小さいものを作れないかなーと思い立ったわけです。

サンプルを作りつつ、ある程度目処はたったものの、

ヘルスチェックも様々あるので、ヘルスチェック部分をプラグイン化できないかと検討中です。

ちなみに、サンプルのコードは以下のとおりです。

https://github.com/shigenobu/PurpleSofa/blob/master/PurpleSofa.SampleProxy/Program.cs

ちょっとわかりにくいのですが、

上手く溜め込んで、バックエンド・フロントエンドとやり取りする

というのがポイントでしょうか。

要はプロキシはTCP端点をフロントとバックの2つで担当することになるので、

フロントとバックが繋がっていない状態を考慮して、メッセージを溜め込んでおく必要があるということです。

やっている人が少ないのですが、golangでは公式ライブラリとしてあるようなので、

そういった実装も参考にさせていただきました。

.NET8もリリースされたので、そろそろTCPプロキシサーバーを着手していければと考えています。

以上

投稿日時:2023年11月28日 14:03   カテゴリー:c#  

前回投稿から、しばらくたちましたが、

0.1.0から少しずつ機能追加・修正を繰り返し、

0.2.0をリリースしました。

https://github.com/shigenobu/ebonyrack/releases/tag/v0.2.0

(最新はこちら)https://github.com/shigenobu/ebonyrack/releases

前回書いていて、実装したかった分ですが、とりあえず以下の内容で対応しています。

むずい。ペンディング。

むずい。ペンディング。

こちらは、0.2.0でアウトライン機能を実装しました。

アウトラインの枠内を動かすことで、右側のワークスペースが一緒に動きます。

逆もまた同じです。

今まで、グラフィックスを取得すると、後続が描画されないということで諦めていたのですが、

    var rect = workspace.getBounds();
    var captureImage =
        new BufferedImage(rect.width, rect.height,
            BufferedImage.TYPE_INT_ARGB);
    var cg = captureImage.getGraphics();
    workspace.printComponents(cg);
    cg.dispose();

    var g2 = (Graphics2D) g.create();
    g2.drawImage(captureImage, 0, 0, w, h, new Color(73, 70, 44, 8), null);
    g2.dispose();

なんて感じで「printComponents」メソッドを使うことで上手く描画できました。

画像・DDLともに出力時に保存先を選択できるようにしました。

最後に出力した保存先は、次回保存するときにデフォルトで選択されるようになりました。

DDLについては、シーケンス・テーブル・外部キー、を選択して出力できるようにしました。

いつかやる。(かも)

だいぶできてきた感じはあるものの、

まだ対応しきれない細かい部分は結構ある感じです。

直近では、プロジェクトを開いたときに、

ワークスペースのスクロールバーの位置が調整できていないことがあるので、

それを直していければとは考えています。

ひとまず、当面はUI改善を進めつつ、パーティンションの機能を追加できればとは考えています。

以上

投稿日時:2023年11月28日 13:45   カテゴリー:java, mariadb, mysql  

ASP.NETで、JSONなどのように複雑な形のリクエストをバリデーションする場合、

一発で検証する方法がなく、苦労していた。

どうにか再帰的にできないかな〜と思っていたところ、

よいライブラリがあったので、紹介します。

https://github.com/tgharold/RecursiveDataAnnotationsValidation

こいつはとても素晴らしいです。(マイクロソフトがちゃんとやってほしい気もするが。。)

(入力定義)

public class Card
{
    [Required]
    public int? CardId { get; set; }
    
    [Required]
    public string CardName { get; set; }
}

public class Req
{
    [Required]
    [Range(0, 10)]
    public int? UserId { get; set; }
    
    [MyValidationCollectionLength(Min = 4, Max = 10)] // 独自のバリデーション
    public List<Card> CardList { get; set; }
}

(検証コード)

var req = new Req
{
    CardList = new List<Card>()
};
req.CardList.Add(new Card());
req.CardList.Add(new Card{CardId = 1, CardName = "hoge"});
req.CardList.Add(new Card{CardId = 2, CardName = ""});

var validator = new RecursiveDataAnnotationValidator();
var validationResults = new List<ValidationResult>();
var result = validator.TryValidateObjectRecursive(req, validationResults);

(検証結果をJSON化したもの)

[
  {
    "MemberNames": [
      "UserId"
    ],
    "ErrorMessage": "The UserId field is required."
  },
  {
    "MemberNames": [
      "CardList"
    ],
    "ErrorMessage": "The field CardList is invalid."
  },
  {
    "MemberNames": [
      "CardList[0].CardId"
    ],
    "ErrorMessage": "The CardId field is required."
  },
  {
    "MemberNames": [
      "CardList[0].CardName"
    ],
    "ErrorMessage": "The CardName field is required."
  },
  {
    "MemberNames": [
      "CardList[2].CardName"
    ],
    "ErrorMessage": "The CardName field is required."
  }
]

という具合に、ちゃんと再帰的に検証してくれます。

APIなんかで複雑なリクエストを検証するときは大いに機能するかと思います。

素晴らしいですね。

以上

投稿日時:2023年07月26日 17:02   カテゴリー:c#  

ショートタームサポートですが、

2023年6月にMariaDB11.0がGAされました。

詳細は以下から。

https://mariadb.com/kb/en/changes-improvements-in-mariadb-11-0/

で、今回のリリースでは、

オプティマイザのコストモデルに大きな修正が入っているのが特徴のようです。

自分としては、

innodb_flush_method

パラメータがdeprecatedになっており、

以下の4つのパラメータに分解されるようです。

  • innodb_log_file_write_through
  • innodb_log_file_buffering
  • innodb_data_file_write_through
  • innodb_data_file_buffering

ログ(WALログ?バイナリログ?それとも2つとも?)とデータによって、

DISKフラッシュをわけるようです。

とはいえ、ちょっと気になるのは、

https://mariadb.com/kb/en/innodb-system-variables/#innodb_flush_method

というページに、

From MariaDB 11.0, if set to one of the following values, then the values of the four boolean flags will be set as follows:

O_DSYNC: 
    innodb_log_file_write_through=ON, 
    innodb_data_file_write_through=ON, 
    innodb_data_file_buffering=OFF, 
    and (if supported) innodb_log_file_buffering=OFF.

fsync, littlesync, nosync, or (Microsoft Windows specific) normal: 
    innodb_log_file_write_through=OFF, 
    innodb_data_file_write_through=OFF, 
    and innodb_data_file_buffering=ON. 

という記述があり、よく見てみると、「O_DIRECTないじゃん」って思ったわけです。

正確には、innodb_flush_methodがなくなった場合、

「O_DIRECTできないじゃん」ということです。

「O_DIRECT」といえば、OSキャッシュをしない、いわゆるダイレクトIOであり、

LINUX環境では設定している人も多いハズ。

(O_DIRECT_NO_FSYNCってのもあり、mysqlのdedicated serverを使うとこっちになることもあるよう)

で、かわりに「O_DSYNC」となるわけだが、こいつの真偽のほどがわからん。。

調べてみると、「O_DIRECT」より速いけど条件付きだよとか、

SSDなら「O_DIRECT」より速いけど一貫性が低いよ(fsyncの回数が少ない?)なんてのもあり、

ちょっと何が正しいのかよくわからん状況です。

11系のLTSが出るまでは時間ありそうなので、

mysqlの動きと合わせて、少し注視しておいたほうがよさげな気がしてます。

あと、自分の作っているmagentadeskも11.0に対応済みです。

https://github.com/shigenobu/magentadesk

以上

投稿日時:2023年07月26日 16:44   カテゴリー:mariadb  

最近知りました。

詳細については、以下を参考ください。

https://github.com/dotnet/runtime/issues/67214

本件ですが、

  • WINDOWSは問題なし
  • MACはダメ
  • LINUXはダメ

ということのようで、LINUXでやってみました。

環境は以下の通りです。

$ cat /etc/os-release
NAME="Pop!_OS"
VERSION="22.04 LTS"

$ dotnet --version
6.0.402

(1. 同期のダメな場合)

public class Program
{
    public static void Main(string[] args)
    {
        try
        {
            Console.WriteLine("main");
            throw new Exception();
        }
        catch (Exception e)
        {
            Console.WriteLine("error");
            throw; // ←こいつが原因
        }
        finally
        {
            Console.WriteLine("finally");   // ここを通過しない
        }
    }
}

(2. 同期でOKな場合)

public class Program
{
    public static void Main(string[] args)
    {
        try
        {
            try
            {
                Console.WriteLine("main");
                throw new Exception();
            }
            catch (Exception e)
            {
                Console.WriteLine("error");
                throw; // ←こいつがいてもfinallyに入る
            }
            finally
            {
                Console.WriteLine("finally");   // 上位のエラーハンドラーがいればOK
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("error - wrapper");
        }
    }
}

(3. 非同期の場合)

public class Program
{
    public static async Task Main(string[] args)
    {
        try
        {
            Console.WriteLine("main");
            throw new Exception();
        }
        catch (Exception e)
        {
            Console.WriteLine("error");
            throw; // ←こいつがいてもfinallyに入る
        }
        finally
        {
            Console.WriteLine("finally");   // async修飾子があればOK
        }
    }
}

(4. NET6からの簡易構文の場合)

try
{
    Console.WriteLine("main");
    throw new Exception();
}
catch (Exception e)
{
    Console.WriteLine("error");
    throw; // ←こいつがいるとダメ
}
finally
{
    Console.WriteLine("finally");   // ここを通過しない
}

以上のように、4つのパターンで試してみました。

asyncの場合は何も気にする必要はないですが、他パターンでは一考が必要かなと。

ちなみに以下のようなエラーになります。

Unhandled exception. System.Exception: Exception of type 'System.Exception' was thrown.

これって、コンテナでやるときにやばいかなと思う。。

気をつけてください。

また、シャットダウンハンドラー(以下のようなコード)を仕込んでみましたが、

動いたのは、「2. 同期でOKな場合」だけでした。

そもそも、asyncはシャットダウンハンドラーって使えない?(要調査)

AppDomain.CurrentDomain.ProcessExit += new EventHandler(ShutdownHander);
public static void ShutdownHander(object sender, EventArgs e)
{
    Console.WriteLine("shutdown");
}

(追記)

Unhandled exceptionは、ProcessExitには反応しないようです。

こちらを使う必要があります。

https://learn.microsoft.com/ja-jp/dotnet/api/system.appdomain.unhandledexception?view=net-8.0

以上

投稿日時:2023年05月18日 18:00   カテゴリー:c#