IBM Cloud Data Engine(旧SQL Query)は2024年1月18日をもって非推奨となり、2024年2月18日以降、新規インスタンスの作成が出来なくなりました。さらに、2025年1月18日をもってEoSとなるため、現在ご利用のインスタンスから後継サービスであるAnalytics Engineなどの利用へ変更する必要があります。
はじめに
Red Hat OpenShift on IBM Cloud(ROKS)のログを、IBM Log Analysis(旧LogDNA)に出力していて、そのログをIBM Cloud Object Storage(ICOS)にアーカイブしているとします。
そのようなICOS上のログを、IBM Cloud Data Engine(旧SQL Query)で解析する例を以前書きました。
状況
この検索対象にROKSのログが含まれているときに、このようなエラーが発生するようになりました。
このようなエラー文言で色々検索しても、欲しい情報になかなかヒットしないです。
SQL execution failed
Found duplicate column(s) in the data schema: name, namespace
If you open a support ticket, it will already contain a reference to this job. Select the appropriate account in the console.
原因
原因としては、例えばnamespace
とNamespace
というように、大文字小文字の違いを除いた同じ名前のフィールドがログの中に含まれてしまっているためです。
具体的には以下のように、OpenShift(Kubernetes)のネームスペースによって、その名前が入っているフィールド名が全部小文字だったり、頭文字が大文字だったりしました。
"namespace": "ibm-observe"
"Namespace": "openshift-marketplace"
このようログが混在したものをSTORED AS JSON
で読み解こうとすると、先のエラーが発生してしまうようです。
解決策
こちらに記載されていました。
Query data with an unstable schema
https://cloud.ibm.com/docs/sql-query?topic=sql-query-overview#query-logs
STORED AS JSON
としていたところを、STORED AS TEXT
にして、必要なフィールドをget_json_object
で持ってくるようにします。
例えば、このようにしたかったことを、
SELECT _source._line as line
FROM cos://jp-tok/ICOSBUCKETNAME/year=2022/month=12/* STORED AS JSON
WHERE _source._app = 'アプリ名' AND _source._line LIKE '%メッセージIDとか%'
このようにすれば、欲しい結果が得られるようになります。
WITH logs (
SELECT get_json_object(value, "$._source._app") as app,
get_json_object(value, "$._source._line") as line
FROM cos://jp-tok/ICOSBUCKETNAME/year=2022/month=10/day=31/* STORED AS TEXT
)
SELECT line
FROM logs
WHERE app = 'アプリ名' AND line LIKE '%メッセージIDとか%'
おまけ
解決策にあるクエリーを見ると、LogDNAのログに含まれるUNIX時間のタイムスタンプ_ts
をハンドリングしています。
これを参考にしつつ、せっかくなので日本時間で表示するには、以下のようにします。
WITH logs (
SELECT get_json_object(value, "$._source._app") as app,
get_json_object(value, "$._source._line") as line,
from_unixtime(32400 + get_json_object(value, "$._source._ts") / 1000, 'yyyy-MM-dd HH:mm:ss') as timestamp
FROM cos://jp-tok/ICOSBUCKETNAME/year=2022/month=10/day=31/* STORED AS TEXT
)
SELECT timestamp, line
FROM logs
WHERE app = 'アプリ名' AND line LIKE '%メッセージIDとか%'
ただし、おそらくLogDNAが受け取ったタイミングの時刻なので、ログ本体に出力時点の時刻が出ている場合、厳密に見るならばそちらを使用するべきですね。
以上。
きっと忘れた頃に同じことで悩むと思うので、その時には検索にヒットするといいなと思いつつの書き込みでした。