C# Tips | ログ・例外・診断:環境情報取得

C# C#
スポンサーリンク

はじめに:環境情報取得は「どこで・どんな設定で動いているか」を数字と言葉で残すこと

業務システムで一番困るのは、 「開発環境では再現しないのに、本番だけでバグが出る」 「同じコードなのに、サーバーによって挙動が違う」 という状況です。

こういうときに必ず必要になるのが 環境情報 です。

どの OS か どの .NET ランタイムか 何ビットプロセスか どのマシン名・ユーザー名か どのカルチャ・タイムゾーンか

こういった情報を ログにきちんと残しておくことで、

「この不具合は、特定の環境だけで起きている」 「設定の違いが原因だ」

といった切り分けができるようになります。

ここでは、初心者向けに

  • Environment クラスで取れる基本情報
  • OS・プロセス・CPU・メモリなどの環境情報
  • 実務で使える「環境情報ダンプユーティリティ」
  • いつ・どこで環境情報をログに残すべきか

を、例題付きでかみ砕いて説明します。

Environment クラスで取れる基本的な環境情報

OS・マシン名・ユーザー名・プロセス情報など

C# では、環境情報の入口としてまず覚えるべきなのが System.Environment クラスです。 ここから、かなり多くの「今動いている環境の情報」を取得できます。

代表的なものをまとめて見てみます。

public static void ShowBasicEnvironment()
{
    Console.WriteLine($"OSVersion: {Environment.OSVersion}");
    Console.WriteLine($"Is64BitOperatingSystem: {Environment.Is64BitOperatingSystem}");
    Console.WriteLine($"Is64BitProcess: {Environment.Is64BitProcess}");
    Console.WriteLine($"MachineName: {Environment.MachineName}");
    Console.WriteLine($"UserName: {Environment.UserName}");
    Console.WriteLine($"CurrentDirectory: {Environment.CurrentDirectory}");
    Console.WriteLine($"ProcessorCount: {Environment.ProcessorCount}");
}
C#

それぞれの意味は、感覚的にはこんな感じです。

OSVersion どの OS か(Windows のバージョンなど)

Is64BitOperatingSystem OS が 64bit かどうか

Is64BitProcess このアプリが 64bit プロセスかどうか(AnyCPU / x86 / x64 の違い)

MachineName サーバー名・PC 名

UserName このプロセスを動かしているユーザー(サービスアカウントなど)

CurrentDirectory 「カレントディレクトリ」(相対パスの基準になる場所)

ProcessorCount 論理 CPU コア数(並列処理の設計に関係する)

ここでの重要ポイントは、 「バグ報告に必ず書いてほしい情報の多くが、コードから自動で取れる」 ということです。

OS・ランタイム・カルチャ・タイムゾーンなどの情報

「どの .NET」「どの文化圏」「どの時間帯」で動いているか

環境差でバグが出やすいのが、 ランタイムのバージョン、カルチャ(言語・地域)、タイムゾーンです。

これらもコードから取得できます。

using System;
using System.Globalization;

public static void ShowRuntimeAndCulture()
{
    Console.WriteLine($".NET Runtime: {Environment.Version}");
    Console.WriteLine($"CurrentCulture: {CultureInfo.CurrentCulture}");
    Console.WriteLine($"CurrentUICulture: {CultureInfo.CurrentUICulture}");
    Console.WriteLine($"TimeZone: {TimeZoneInfo.Local.DisplayName}");
}
C#

意味をざっくり言うと、

Environment.Version 今動いている .NET ランタイムのバージョン

CurrentCulture 日付・数値・通貨などのフォーマットに使われる文化圏(例:ja-JP)

CurrentUICulture UI の言語(リソースの選択に使われる)

TimeZoneInfo.Local ローカルタイムゾーン(例:Tokyo Standard Time)

ここでの重要ポイントは、 「日付・数値・文字列の挙動はカルチャとタイムゾーンに強く依存する」 ということです。

例えば、

  • DateTime.ToString() の表示形式
  • double.Parse("1,23") の解釈
  • 日付の「日曜始まりか月曜始まりか」

などは、カルチャによって変わります。

「開発環境(ja-JP)では動くのに、本番(en-US)では落ちる」 というバグは、環境情報をログに残していないと見つけづらくなります。

実務で使える「環境情報ダンプユーティリティ」

一度にまとめてログに吐き出せるようにしておく

毎回バラバラに Environment を呼ぶのは面倒なので、 「環境情報をまとめてダンプするユーティリティ」 を作っておくと便利です。

ILogger と組み合わせた例を見てみましょう。

using System;
using System.Diagnostics;
using System.Globalization;
using Microsoft.Extensions.Logging;

public static class EnvironmentLogger
{
    public static void LogEnvironment(ILogger logger, string context)
    {
        using var process = Process.GetCurrentProcess();

        logger.LogInformation(
            "EnvironmentDump Context={Context} " +
            "MachineName={MachineName} UserName={UserName} " +
            "OSVersion={OSVersion} Is64BitOS={Is64BitOS} Is64BitProcess={Is64BitProcess} " +
            "ProcessorCount={ProcessorCount} " +
            "CurrentDirectory={CurrentDirectory} " +
            "RuntimeVersion={RuntimeVersion} " +
            "CurrentCulture={CurrentCulture} CurrentUICulture={CurrentUICulture} " +
            "TimeZone={TimeZone} " +
            "ProcessId={ProcessId} ProcessName={ProcessName}",
            context,
            Environment.MachineName,
            Environment.UserName,
            Environment.OSVersion,
            Environment.Is64BitOperatingSystem,
            Environment.Is64BitProcess,
            Environment.ProcessorCount,
            Environment.CurrentDirectory,
            Environment.Version,
            CultureInfo.CurrentCulture,
            CultureInfo.CurrentUICulture,
            TimeZoneInfo.Local.DisplayName,
            process.Id,
            process.ProcessName);
    }
}
C#

使い方の例です。

// アプリ起動時に一度だけ
EnvironmentLogger.LogEnvironment(_logger, "AppStart");

// 重大なエラー発生時にも
EnvironmentLogger.LogEnvironment(_logger, "FatalError");
C#

ログには、例えばこんな行が残ります。

「EnvironmentDump Context=AppStart MachineName=WEB01 UserName=svc_app OSVersion=Microsoft Windows NT 10.0.20348.0 Is64BitOS=True Is64BitProcess=True ProcessorCount=8 CurrentDirectory=C:\apps\MyService RuntimeVersion=7.0.10 CurrentCulture=ja-JP CurrentUICulture=ja-JP TimeZone=(UTC+09:00) Osaka, Sapporo, Tokyo ProcessId=1234 ProcessName=MyService」

ここでの重要ポイントは、

「環境情報は“まとめて一行で”残す」 「いつ・どの文脈で取ったか(Context)を付ける」

ということです。

これにより、

  • 本番サーバーごとの環境差
  • 起動時とエラー時の環境の違い

などを後から比較しやすくなります。

いつ環境情報をログに残すべきか

起動時・重大エラー時・診断モード開始時

環境情報は、毎秒取るようなものではありません。 「ここで環境を知っておきたい」というタイミングに絞ってログに残すのが実務的です。

代表的なタイミングは次のような場面です。

アプリ起動時 「このバージョンのアプリが、どの環境で動いているか」を記録しておく。

重大なエラー発生時 「このエラーが起きたときの環境」をセットで残しておく。

診断モード開始時 「今から負荷試験します」「今から調査モードに入ります」といったタイミング。

ここでの重要ポイントは、 「環境情報は“バグ報告のテンプレ”をコードで自動化したもの」 という感覚です。

人間が「OS は?」「何ビット?」「カルチャは?」と聞き回る代わりに、 アプリが自分でそれをログに書いておいてくれるイメージです。

まとめ:環境情報取得は“バグの再現条件を機械的に残す”ためのユーティリティ

環境情報取得の本質を一言で言うと、

「このアプリが、 どの OS・どの .NET・どのマシン・どのユーザー・どのカルチャ・どのタイムゾーンで動いていたかを、 ログとして機械的に残し、 バグの再現条件や環境差を後から正確に語れるようにする」

ことです。

押さえておきたいポイントは次の通りです。

  • Environment クラスから、OS・マシン名・ユーザー名・プロセス情報・CPU数などを簡単に取得できる。
  • CultureInfoTimeZoneInfo から、カルチャ・タイムゾーンを取得でき、日付・数値・文字列の挙動に直結する。
  • EnvironmentLogger のようなユーティリティを作り、「環境情報をまとめて一行でログに残す」形にしておくと実務で使いやすい。
  • 起動時・重大エラー時・診断モード開始時など、「ここで環境を知っておきたい」タイミングでログを出すのが現実的。

ここまでイメージできていれば、 「本番だけで起きる謎のバグ」に対して、 “環境情報という武器”を持った状態で戦えるようになります。

タイトルとURLをコピーしました