2014年12月の臭い
数年前から妻に「仕事を変えて」と言われていました。転職の理由は色々で、ひとつには絞れないけど、記憶に残ることがありました。人間、えらく疲れると通常とは異なる臭いを発するらしい。それが疲労臭という。2014年12月はそんな臭いを撒き散らしていたらしい。
症状
酷く足が臭く、脹脛が硬くなった。この臭いが強烈で、履いていた靴がやたらと臭くなった。メレルのごつい靴を履いていたが、臭いが取れずに「靴選科」で4500円のクリーニングに出した記憶があります。
その頃は仕事の追い込みで、客先にカジュアルウェアで土日、昼夜関係なく仕事をしていました。2日連続で徹夜したとき、靴を脱いで、靴下で歩き回ると嫌な臭いがカーペットに残りました。他の人がファブリーズで、私が歩いたところを消臭して回ったぐらいです。
疲労臭
あとから知ったのですが、これは疲労臭という症状でした。腎臓、肝臓の機能が低下して、アンモニア臭を発するという状況とぴたりと一致します。このころ、リフレクソロジーに行ったときも、ふくらはぎが異様にかたいとしてきされていました。身体が悲鳴を上げていたのは自覚していましたが、この仕事の切れ目までと無理を続けていました。
なんだか臭う…それはお疲れのサイン「疲労臭」かも?
妻の指摘は正しかったわけで、鼻を膨らませて「だからいったでしょ」とドヤ顔決めてます。あれを突き抜けると、過労死が待っていたのかもと思うと少し寒くなります。身体がダウンする手前まで頑張った。故に清々として、次の職場を探すことができたと思うのは不健康でしょうか。
SASプログラムとログを解析するユーティリティを開発するための備忘録です。This is a memo to develop utility that analyzes the SAS log.
2016年2月6日土曜日
2016年2月1日月曜日
SAS Log Utility, 多言語対応の仕組みを考える
多言語対応で必要なものは何?
設定ファイルは、ISO言語省略名ごとに保持できるようにしたい。
どこに、設定ファイルを保持するか?
!SASROOT\nls\ja の形に倣って設定ファイルを配置するか?
それとも、設定ファイルの後ろにISO言語省略名を付与するのか?
LOCALEの取得は、Windows.GetLocaleInfoでできる。
言語の切り替えは、メニューから行う。
切り替えはツールの再起動なしで、反映できるようにしたい。
言語を切り替えて、ダイアログの表示を切り替えられるか?
reinit.ReinitializeFormsは使えるのか?
reinit.LoadNewResourceModuleは使えるのか?
他に使い出のあるものは何?
マイグレーション案件、面倒なことが色々ある。
何か効率化できるネタはないか。
VAの構成って面倒、設定だけではなくエビデンスの取得もできる何かが欲しい。
移行で毎回手を焼くのが、過去データの移送と変換です。
量が多いので、並列化したり、夜間に差分検出して移送する、中断、再開の制御を入れています。
他には?
BI Serverの構成が面倒です。
SMCの管理は苦手なのです、私はね。
設定ファイルは、ISO言語省略名ごとに保持できるようにしたい。
どこに、設定ファイルを保持するか?
!SASROOT\nls\ja の形に倣って設定ファイルを配置するか?
それとも、設定ファイルの後ろにISO言語省略名を付与するのか?
LOCALEの取得は、Windows.GetLocaleInfoでできる。
言語の切り替えは、メニューから行う。
切り替えはツールの再起動なしで、反映できるようにしたい。
言語を切り替えて、ダイアログの表示を切り替えられるか?
reinit.ReinitializeFormsは使えるのか?
reinit.LoadNewResourceModuleは使えるのか?
他に使い出のあるものは何?
マイグレーション案件、面倒なことが色々ある。
何か効率化できるネタはないか。
VAの構成って面倒、設定だけではなくエビデンスの取得もできる何かが欲しい。
移行で毎回手を焼くのが、過去データの移送と変換です。
量が多いので、並列化したり、夜間に差分検出して移送する、中断、再開の制御を入れています。
他には?
BI Serverの構成が面倒です。
SMCの管理は苦手なのです、私はね。
2016年1月30日土曜日
きっと役立つ、バグになりそうなNOTE:のチェック
SAS Log Utilityには、エラーでもなく、ワーニングでもないけど、バグになりそうなメッセージをチェックする機能があります。2013年頃投稿、2016年1月30日更新です。
関数の引数無効とかは、意外と気がつきにくいです。
- 変数 ABC は初期化されていません
- 以下の箇所で文字値を数値に変換しました
- 以下の箇所で数値を文字値に変換しました
- ステートメントに BY値を繰り返すデータセットが複数あります
- 欠損値を含んだ計算により、以下の箇所で欠損値が生成されました
- 切り捨てられた行があります
- カラム999で0による割り算がありました
- 関数XYZ(行999 カラム999の引数は無効です
- LOST CARD.
- NOEXECオプションが指定
- ループが発生したため、DATAステップの実行を中止しました
- 引用符で囲まれた文字列の後の識別子の意味は
- 数値をプリントするには小さすぎるW.D出力形式
- ライブラリABCは存在しません
- クエリは元のデータに要約統計量の結果を再マージします
- データセットABCにオブザベーションがありません
- ファイルABC(memtype=DATA)は見つかりませんが、DELETEステートメントに存在します
- ABCは未参照のラベル定義です
- ABCに対して、無効なデータが行999カラム999にあります
- ステートメントが行の終端に達したので、次の行を読み込みます
- 要約化中にディスク処理が発生しました
- CASE式にELSE句がありません
関数の引数無効とかは、意外と気がつきにくいです。
SAS Log Utility 1.6.1.8, 不具合修正
Vectorに登録の申請をしました。
修正したのは以下の点です。
ステータスバーに言語省略名を表示したのは、多言語対応の準備です。
行末のタブ又は空白を削除するようにしたのは、SASログをEXCELファイルに貼って渡す人がいて、処理の区切りを正確に判定できなかったためです。これがメモリリークの原因のひとつになっていました。ちなみに、EXCELに貼り付けて渡すとダブルクォートがエスケープされて、正しくパースできないことがありますので、私はWinZipで圧縮して渡します。
記録まで
修正したのは以下の点です。
- NOTE:でチェックするパターンを追加
- ステータスバーにISO言語省略名を表示
- ログの行末に追加されている空白又はタブを削除して処理
- ListViewのソートの不具合を修正
ステータスバーに言語省略名を表示したのは、多言語対応の準備です。
行末のタブ又は空白を削除するようにしたのは、SASログをEXCELファイルに貼って渡す人がいて、処理の区切りを正確に判定できなかったためです。これがメモリリークの原因のひとつになっていました。ちなみに、EXCELに貼り付けて渡すとダブルクォートがエスケープされて、正しくパースできないことがありますので、私はWinZipで圧縮して渡します。
記録まで
2016年1月28日木曜日
SAS Log Inspector 1.3.1.2, リリース
機能は変えず、組み込みのマッチングパターンを24種類に増やしました。どんなパターンが定義されているかは、以下の画像をご覧ください。Vectorに公開の依頼を投げました。
SAS Log Inspectorの機能
- 複数のログファイルからエラー、バグに繋がるNOTEを集計
- 日本語と英語版のメッセージに対応
- Excelファイルにログをチェックした結果をエクスポート
- 任意のチェック項目を検査対象から外すことができる
- Notepadを起動して、該当のログファイルを参照できる
- マッチングパターンを画面から追加、修正できる
2016年1月27日水曜日
やること
ログを検査するパターン追加
NOTE: CASE式にELSE句がありません。すべてのWHEN句の条件に合わなかった場合、CASE式の結果は欠損値になります。
APPENDのパターン対応
NOTE: WORK.ABCをWORK.DEFに追加します。
NOTE: データセットWORK.ABCから0オブザベーションを読み込みました。
NOTE: 0オブザベーションが追加されました。
NOTE: データセットWORK.DEFは0オブザベーション、20変数です。
NOTE: PROCEDURE APPEND処理(合計処理時間):
処理時間 0.00 秒
CPU時間 0.01 秒
NOTE: Appending WORK.ONE to WORK.BASE.
WARNING: Variable c was not found on BASE file. The variable will not be added to the BASE file.
WARNING: Variable a has different lengths on BASE and DATA files (BASE 3 DATA 4).
WARNING: Variable b has different lengths on BASE and DATA files (BASE 5 DATA 4).
WARNING: Variable d was not found on DATA file.
NOTE: FORCE is specified, so dropping/truncating will occur.
NOTE: There were 4 observations read from the data set WORK.ONE.
NOTE: 4 observations added.
NOTE: The data set WORK.BASE has 4 observations and 4 variables.
NOTE: PROCEDURE APPEND used (Total process time):
real time 0.15 seconds
cpu time 0.06 seconds
2016年1月17日日曜日
Windows.GetLocaleInfoでLanguage Tagを取得
ツールのI18Nの検討メモです。
設定ファイルの言語を区別するため、Language Tag(ja, JP, en-usとか)を取得する方法を探しています。ログ解析の設定を日本語、英語と切り替えられるようにするための調査です。ネット上を探すとそのまま使えるサンプルが見つからないため、DelphiForFun HomeにあったDemoのコードを参考にしてサンプルコードを作りました。
試すときは、Formの上に、ButtonとListViewを配置し、ListViewの形式をvsReport、カラムを5つ定義してください。参考にしたのは以下のURLの情報です。
Locale Constants Demo
Language Tagの定義を探していたら、以下の情報が見つかりました。昔々、VAX Notes上でお世話になった記憶が微かにあります。
国際化プログラミング
設定ファイルの言語を区別するため、Language Tag(ja, JP, en-usとか)を取得する方法を探しています。ログ解析の設定を日本語、英語と切り替えられるようにするための調査です。ネット上を探すとそのまま使えるサンプルが見つからないため、DelphiForFun HomeにあったDemoのコードを参考にしてサンプルコードを作りました。
試すときは、Formの上に、ButtonとListViewを配置し、ListViewの形式をvsReport、カラムを5つ定義してください。参考にしたのは以下のURLの情報です。
Locale Constants Demo
Language Tagの定義を探していたら、以下の情報が見つかりました。昔々、VAX Notes上でお世話になった記憶が微かにあります。
国際化プログラミング
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, shellapi, Vcl.ComCtrls;
type
TForm1 = class(TForm)
ListView1: TListView;
Button1: TButton;
procedure FormActivate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
type
TRec = Record
Code: Cardinal;
Name: String;
Text: String;
end;
const
rSet: Array [0 .. 79] of TRec = (
(Code: LOCALE_ILANGUAGE; Name: '言語ID'; Text: 'LOCALE_ILANGUAGE'),
(Code: LOCALE_SLANGUAGE; Name: '言語名'; Text: 'LOCALE_SLANGUAGE'),
(Code: LOCALE_SENGLANGUAGE; Name: '言語英語名'; Text: 'LOCALE_SENGLANGUAGE'),
(Code: LOCALE_SABBREVLANGNAME; Name: '言語省略名'; Text: 'LOCALE_SABBREVLANGNAME'),
(Code: LOCALE_SNATIVELANGNAME; Name: '言語固有名'; Text: 'LOCALE_SNATIVELANGNAME'),
(Code: LOCALE_ICOUNTRY; Name: '国コード'; Text: 'LOCALE_ICOUNTRY'),
(Code: LOCALE_SCOUNTRY; Name: '国名'; Text: 'LOCALE_SCOUNTRY'),
(Code: LOCALE_SENGCOUNTRY; Name: '国英語名'; Text: 'LOCALE_SENGCOUNTRY'),
(Code: LOCALE_SABBREVCTRYNAME; Name: '国省略名'; Text: 'LOCALE_SABBREVCTRYNAME'),
(Code: LOCALE_SNATIVECTRYNAME; Name: '国固有名'; Text: 'LOCALE_SNATIVECTRYNAME'),
(Code: LOCALE_IDEFAULTLANGUAGE; Name: 'デフォルト言語ID'; Text: 'LOCALE_IDEFAULTLANGUAGE'),
(Code: LOCALE_IDEFAULTCOUNTRY; Name: 'デフォルト国コード'; Text: 'LOCALE_IDEFAULTCOUNTRY'),
(Code: LOCALE_IDEFAULTCODEPAGE; Name: 'デフォルトOEMコードページ'; Text: 'LOCALE_IDEFAULTCODEPAGE'),
(Code: LOCALE_IDEFAULTANSICODEPAGE; Name: 'デフォルトANSIコードページ'; Text: 'LOCALE_IDEFAULTANSICODEPAGE'),
(Code: LOCALE_IDEFAULTMACCODEPAGE; Name: 'デフォルトMACコードページ'; Text: 'LOCALE_IDEFAULTMACCODEPAGE'),
(Code: LOCALE_FONTSIGNATURE; Name: 'フォント署名'; Text: 'LOCALE_FONTSIGNATURE'),
(Code: LOCALE_SISO639LANGNAME; Name: 'ISO言語省略名'; Text: 'LOCALE_SISO639LANGNAME'),
(Code: LOCALE_SISO3166CTRYNAME; Name: 'ISO国省略名'; Text: 'LOCALE_SISO3166CTRYNAME'),
(Code: LOCALE_SLIST; Name: '区切り記号'; Text: 'LOCALE_SLIST'),
(Code: LOCALE_IMEASURE; Name: '単位'; Text: 'LOCALE_IMEASURE'),
(Code: LOCALE_SDECIMAL; Name: '小数点の記号'; Text: 'LOCALE_SDECIMAL'),
(Code: LOCALE_STHOUSAND; Name: '桁区切り記号'; Text: 'LOCALE_STHOUSAND'),
(Code: LOCALE_SGROUPING; Name: '区切る桁数'; Text: 'LOCALE_SGROUPING'),
(Code: LOCALE_IDIGITS; Name: '小数点以下の桁数'; Text: 'LOCALE_IDIGITS'),
(Code: LOCALE_ILZERO; Name: '少数前ゼロの桁数'; Text: 'LOCALE_ILZERO'),
(Code: LOCALE_INEGNUMBER; Name: '負の値の形式'; Text: 'LOCALE_INEGNUMBER'),
(Code: LOCALE_SNATIVEDIGITS; Name: '0から9の表記'; Text: 'LOCALE_SNATIVEDIGITS'),
(Code: LOCALE_SPOSITIVESIGN; Name: '正の記号'; Text: 'LOCALE_SPOSITIVESIGN'),
(Code: LOCALE_SNEGATIVESIGN; Name: '負の記号'; Text: 'LOCALE_SNEGATIVESIGN'),
(Code: LOCALE_IPOSSIGNPOSN; Name: '正の記号の位置'; Text: 'LOCALE_IPOSSIGNPOSN'),
(Code: LOCALE_INEGSIGNPOSN; Name: '負の記号の位置'; Text: 'LOCALE_INEGSIGNPOSN'),
(Code: LOCALE_SCURRENCY; Name: '通貨記号'; Text: 'LOCALE_SCURRENCY'),
(Code: LOCALE_SINTLSYMBOL; Name: '国際通貨記号'; Text: 'LOCALE_SINTLSYMBOL'),
(Code: LOCALE_SMONDECIMALSEP; Name: '小数点の記号'; Text: 'LOCALE_SMONDECIMALSEP'),
(Code: LOCALE_SMONTHOUSANDSEP; Name: '桁区切り記号'; Text: 'LOCALE_SMONTHOUSANDSEP'),
(Code: LOCALE_SMONGROUPING; Name: '区切る桁数'; Text: 'LOCALE_SMONGROUPING'),
(Code: LOCALE_ICURRDIGITS; Name: '小数点以下の桁数'; Text: 'LOCALE_ICURRDIGITS'),
(Code: LOCALE_IINTLCURRDIGITS; Name: '小数点以下の桁数'; Text: 'LOCALE_IINTLCURRDIGITS'),
(Code: LOCALE_ICURRENCY; Name: '正の値の形式'; Text: 'LOCALE_ICURRENCY'),
(Code: LOCALE_INEGCURR; Name: '負の値の形式'; Text: 'LOCALE_INEGCURR'),
(Code: LOCALE_IPOSSYMPRECEDES; Name: '正の通貨記号の位置'; Text: 'LOCALE_IPOSSYMPRECEDES'),
(Code: LOCALE_IPOSSEPBYSPACE; Name: '正の通貨記号の分離位置'; Text: 'LOCALE_IPOSSEPBYSPACE'),
(Code: LOCALE_INEGSYMPRECEDES; Name: '負の通貨記号の位置'; Text: 'LOCALE_INEGSYMPRECEDES'),
(Code: LOCALE_INEGSEPBYSPACE; Name: '負の通貨記号の分離位置'; Text: 'LOCALE_INEGSEPBYSPACE'),
(Code: LOCALE_SDATE; Name: '区切り記号'; Text: 'LOCALE_SDATE'),
(Code: LOCALE_SSHORTDATE; Name: '短い形式'; Text: 'LOCALE_SSHORTDATE'),
(Code: LOCALE_SLONGDATE; Name: '長い形式'; Text: 'LOCALE_SLONGDATE'),
(Code: LOCALE_IDATE; Name: '短い形式の年月日順'; Text: 'LOCALE_IDATE'),
(Code: LOCALE_ILDATE; Name: '長い形式の年月日順'; Text: 'LOCALE_ILDATE'),
(Code: LOCALE_ICENTURY; Name: '年の桁数'; Text: 'LOCALE_ICENTURY'),
(Code: LOCALE_IDAYLZERO; Name: '日前ゼロの有無'; Text: 'LOCALE_IDAYLZERO'),
(Code: LOCALE_IMONLZERO; Name: '月前ゼロの有無'; Text: 'LOCALE_IMONLZERO'),
(Code: LOCALE_ICALENDARType; Name: 'カレンダの種類'; Text: 'LOCALE_ICALENDARType'),
(Code: LOCALE_IOPTIONALCALENDAR; Name: '追加カレンダの種類'; Text: 'LOCALE_IOPTIONALCALENDAR'),
(Code: LOCALE_IFIRSTDAYOFWEEK; Name: '週の先頭日'; Text: 'LOCALE_IFIRSTDAYOFWEEK'),
(Code: LOCALE_IFIRSTWEEKOFYEAR; Name: '年の先頭月'; Text: 'LOCALE_IFIRSTWEEKOFYEAR'),
(Code: LOCALE_SDAYNAME1; Name: '週の第1日名'; Text: 'LOCALE_SDAYNAME1'),
(Code: LOCALE_SDAYNAME2; Name: '週の第2日名'; Text: 'LOCALE_SDAYNAME2'),
(Code: LOCALE_SDAYNAME3; Name: '週の第3日名'; Text: 'LOCALE_SDAYNAME3'),
(Code: LOCALE_SDAYNAME7; Name: '週の第7日名'; Text: 'LOCALE_SDAYNAME7'),
(Code: LOCALE_SABBREVDAYNAME1; Name: '週の第1日省略名'; Text: 'LOCALE_SABBREVDAYNAME1'),
(Code: LOCALE_SABBREVDAYNAME2; Name: '週の第2日省略名'; Text: 'LOCALE_SABBREVDAYNAME2'),
(Code: LOCALE_SABBREVDAYNAME3; Name: '週の第3日省略名'; Text: 'LOCALE_SABBREVDAYNAME3'),
(Code: LOCALE_SABBREVDAYNAME7; Name: '週の第7日省略名'; Text: 'LOCALE_SABBREVDAYNAME7'),
(Code: LOCALE_SMONTHNAME1; Name: '年の第1月名'; Text: 'LOCALE_SMONTHNAME1'),
(Code: LOCALE_SMONTHNAME2; Name: '年の第2月名'; Text: 'LOCALE_SMONTHNAME2'),
(Code: LOCALE_SMONTHNAME3; Name: '年の第3月名'; Text: 'LOCALE_SMONTHNAME3'),
(Code: LOCALE_SMONTHNAME12; Name: '年の第12月名'; Text: 'LOCALE_SMONTHNAME12'),
(Code: LOCALE_SMONTHNAME13; Name: '年の第13月名'; Text: 'LOCALE_SMONTHNAME13'),
(Code: LOCALE_SABBREVMONTHNAME1; Name: '年の第1月省略名'; Text: 'LOCALE_SABBREVMONTHNAME1'),
(Code: LOCALE_SABBREVMONTHNAME2; Name: '年の第2月省略名'; Text: 'LOCALE_SABBREVMONTHNAME2'),
(Code: LOCALE_SABBREVMONTHNAME3; Name: '年の第3月省略名'; Text: 'LOCALE_SABBREVMONTHNAME3'),
(Code: LOCALE_SABBREVMONTHNAME12; Name: '年の第12月省略名'; Text: 'LOCALE_SABBREVMONTHNAME12'),
(Code: LOCALE_STIME; Name: '区切り記号'; Text: 'LOCALE_STIME'),
(Code: LOCALE_STIMEFORMAT; Name: '時間の形式'; Text: 'LOCALE_STIMEFORMAT'),
(Code: LOCALE_ITIME; Name: '時間制(12/24)'; Text: 'LOCALE_ITIME'),
(Code: LOCALE_ITIMEMARKPOSN; Name: '午前午後記号の位置'; Text: 'LOCALE_ITIMEMARKPOSN'),
(Code: LOCALE_ITLZERO; Name: '時刻前ゼロの有無'; Text: 'LOCALE_ITLZERO'),
(Code: LOCALE_S1159; Name: '午前の記号'; Text: 'LOCALE_S1159'),
(Code: LOCALE_S2359; Name: '午後の記号'; Text: 'LOCALE_S2359')
);
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
Form1.Close;
end;
procedure TForm1.FormActivate(Sender: TObject);
var
buf: array [1 .. 100] of char;
i: integer;
AItem: TListItem;
begin
for i := Low(rSet) to High(rSet) do
begin
Windows.GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, rSet[i].Code, @buf, 100);
AItem := ListView1.Items.Add;
AItem.Caption := Format('%.3d', [i + 1]);
AItem.SubItems.Add(rSet[i].Name);
AItem.SubItems.Add(rSet[i].Text);
AItem.SubItems.Add(Format('%d', [rSet[i].Code]));
AItem.SubItems.Add(string(buf));
end;
end;
end.
登録:
投稿
(
Atom
)


