Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
OpenTelemetry の Log を使いこなそう
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Shota Iwami
July 23, 2025
Technology
2k
7
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
OpenTelemetry の Log を使いこなそう
Jagu'e'r オブザーバビリティ分科会 Meetup #3
https://jaguer-o11y-sre.connpass.com/event/359593/
Shota Iwami
July 23, 2025
More Decks by Shota Iwami
See All by Shota Iwami
モノレポにおけるエラー管理 ~Runbook自動生成とチームメンションの最適化
biwashi
2
1k
Monorepo Error Management: Automated Runbooks and Team-Targeted Alert Distribution
biwashi
2
1.1k
スタートアップ創業期を支えるオブザーバビリティ基盤のこれまでとこれから
biwashi
10
1.7k
モノレポ開発のエラー、誰が見る?Datadog で実現する適切なトリアージとエスカレーション
biwashi
7
1.8k
k6を活用した再現性・拡張性の高い負荷試験基盤の構築
biwashi
13
4.3k
Datadogマニアック機能活用術
biwashi
7
4.4k
feature flag と OpenTelemetry
biwashi
7
2.4k
OpenFeatureと自動生成を活用したフィーチャーフラグの宣言的集約管理
biwashi
20
7.5k
Unified Diff 形式の差分から Go AST を構築して feature flag を自動計装する
biwashi
11
1.6k
Other Decks in Technology
See All in Technology
運用を犠牲にせずコストを制御し事業成長を支える B2B SaaS ID管理基盤におけるS3 Tableのログストレージ活用
kaminashi
1
130
【5分でわかる】セーフィー エンジニア向け会社紹介
safie_recruit
0
53k
AI驚き屋発見器
yama3133
2
390
クラウドセキュリティ入門 ~安全なクラウド利用のための基礎知識~
lhazy
7
5.8k
書籍セキュアAPIについて
riiimparm
0
400
オートマトンと字句解析でRoslynを読む
tomokusaba
0
130
テックカンファレンス三大ステークホルダーの文化人類学 ─ 違いを認め合う関係性作り
bash0c7
5
1.5k
MIRU 2026 チュートリアル
keisuke198619
0
420
データ組織の転換期 一足飛びしない段階的戦略
leveragestech
PRO
0
140
20260724 情シスAI #1 「全従業員をAIネイティブにする」ために情シスがやっていること(公開版)
frtckty
0
150
AWS環境のセキュリティ不安を解消した企業事例 ~よくある課題と対策を一挙公開~
asanoharuki
1
270
Power Automateアップデート情報
miyakemito
0
290
Featured
See All Featured
Abbi's Birthday
coloredviolet
3
8.9k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
1
2.8k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
430
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
240
Measuring & Analyzing Core Web Vitals
bluesmoon
9
940
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
400
GraphQLとの向き合い方2022年版
quramy
50
15k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
10k
How GitHub (no longer) Works
holman
316
150k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Scaling GitHub
holman
464
140k
Transcript
4IPUB*XBNJ]1MBUGPSN&OHJOFFS]OFXNP *OD OpenTelemetry ͷ Log Λ͍͜ͳͦ͏ Jagu'e'r ΦϒβʔόϏϦςΟՊձ Meetup #3
1
ؠݟজଠ*XBNJO Platform Engineer newmo, Inc. 2
ؠݟজଠ*XBNJO Platform Engineer Autonomous Driving Vehicle Team? newmo, Inc. 3
Software Design 5݄߸ 4 4 • ͡Ίʹ • OpenTelemetryͱ •
OpenTelemetryͷجຊΞʔΩςΫνϟ • αϯϓϦϯάઓུͱ࣮ • ܭͷछྨͱબج४ • खಈ/ϥΠϒϥϦ/ࣗಈܭ • TraceProvider • MetricProvider • LoggerProvider • ·ͱΊ 4 “OpenTelemetryೖ” Λدߘ͠·ͨ͠
Software Design 5݄߸ 5 “OpenTelemetryೖ” Λدߘ͠·ͨ͠ 5 • ͡Ίʹ •
OpenTelemetryͱ • OpenTelemetryͷجຊΞʔΩςΫνϟ • αϯϓϦϯάઓུͱ࣮ • ܭͷछྨͱબج४ • खಈ/ϥΠϒϥϦ/ࣗಈܭ • TraceProvider • MetricProvider • LoggerProvider • ·ͱΊ 5
LoggerProviderͷར༻ 6
Logger Provider 7 7 • Trace, Metricsͱগ͠ੑ࣭͕ҧ͏ • طଘͷϩΪϯάϥΠϒϥϦͱ Otel
Λ࿈ܞͤ͞ΔͨΊͷ Bridge ػೳΛఏڙ • ޓੑΛอͪͳ͕Β Trace ͱඥ͚Δ Context ͷՃڞ௨ϑΥʔϚοτʹղੳɾม͢Δͨ ΊͷπʔϧΩοτΛఏڙ 7
Logger Provider 8 8 • Trace, Metricsͱগ͠ੑ࣭͕ҧ͏ • طଘͷϩΪϯάϥΠϒϥϦͱ Otel
Λ࿈ܞͤ͞ΔͨΊͷ Bridge ػೳΛఏڙ • ޓੑΛอͪͳ͕Β Trace ͱඥ͚Δ Context ͷՃڞ௨ϑΥʔϚοτʹղੳɾม͢Δͨ ΊͷπʔϧΩοτΛఏڙ 8
Otel log bridge ΛΘͳ͍߹ 9
10 func (s *slogJSONHandler) Handle( ctx context.Context, r slog.Record, )
error { newRecord := slog.NewRecord(…) ... sc := trace.SpanContextFromContext(ctx) if sc.HasTraceID() { newRecord.AddAttrs( slog.String("trace_id", sc.TraceID().String()), slog.String("trace_flags", sc.TraceFlags().String()), ) if sc.HasSpanID() { newRecord.AddAttrs(slog.String("span_id", sc.SpanID().String())) } } return s.handler.Handle(ctx, newRecord) } Bridge ΛΘͣʹ trace ͱඥ͚ͮΔ߹ • Log Handler ʹcontext ͔Β trace id Λऔಘ • ࣗલͰ attribute ʹՃ
11 func (s *slogJSONHandler) Handle( ctx context.Context, r slog.Record, )
error { newRecord := slog.NewRecord(…) ... sc := trace.SpanContextFromContext(ctx) if sc.HasTraceID() { newRecord.AddAttrs( slog.String("trace_id", sc.TraceID().String()), slog.String("trace_flags", sc.TraceFlags().String()), ) if sc.HasSpanID() { newRecord.AddAttrs(slog.String("span_id", sc.SpanID().String())) } } return s.handler.Handle(ctx, newRecord) } Bridge ΛΘͣʹ trace ͱඥ͚ͮΔ߹ • Log Handler ʹcontext ͔Β trace id Λऔಘ • ࣗલͰ attribute ʹՃ
12 func (s *slogJSONHandler) Handle( ctx context.Context, r slog.Record, )
error { newRecord := slog.NewRecord(…) ... sc := trace.SpanContextFromContext(ctx) if sc.HasTraceID() { newRecord.AddAttrs( slog.String("trace_id", sc.TraceID().String()), slog.String("trace_flags", sc.TraceFlags().String()), ) if sc.HasSpanID() { newRecord.AddAttrs(slog.String("span_id", sc.SpanID().String())) } } return s.handler.Handle(ctx, newRecord) } Bridge ΛΘͣʹ trace ͱඥ͚ͮΔ߹ • Log Handler ʹcontext ͔Β trace id Λऔಘ • ࣗલͰ attribute ʹՃ
Otel log bridge Λ͏߹ 13
lp := initLoggerProvider(ctx) // slogͱOpenTelemetryͷ࿈ܞ logger := otelslog.NewLogger("my-service", otelslog.WithLoggerProvider(lp)) //
τϨʔεͱͷ࿈ܞྫ tracer := otel.Tracer("my-service") ctx, span := tracer.Start(ctx, "operation-name") defer span.End() // contextΛ͢͜ͱͰɺtraceใΛൖ͍ͯ͠Δ logger.InfoContext(ctx, "Start processing", "user_id", "12345", ) OpenTelemetry Logger Provider for Go 14 • ීஈ͍ͬͯΔ slog Λ wrap ͢Δ͚ͩ
lp := initLoggerProvider(ctx) // slogͱOpenTelemetryͷ࿈ܞ logger := otelslog.NewLogger("my-service", otelslog.WithLoggerProvider(lp)) //
τϨʔεͱͷ࿈ܞྫ tracer := otel.Tracer("my-service") ctx, span := tracer.Start(ctx, "operation-name") defer span.End() // contextΛ͢͜ͱͰɺtraceใΛൖ͍ͯ͠Δ logger.InfoContext(ctx, "Start processing", "user_id", "12345", ) OpenTelemetry Logger Provider for Go 15 • ීஈ͍ͬͯΔ slog Λ wrap func initLoggerProvider(ctx context.Context) (*sdklog.LoggerProvider, error) { // ΤΫεϙʔλʔͷઃఆ exporter, _ := otlploggrpc.New(ctx, otlploggrpc.WithEndpoint("localhost:4317"), otlploggrpc.WithInsecure(), ) // LoggerProviderͷઃఆ loggerProvider := sdklog.NewLoggerProvider( sdklog.WithProcessor( sdklog.NewBatchProcessor( exporter, ), ), ) return loggerProvider, nil }
Logger Provider 16 16 16
Logger Provider 17 17 17
Logger Provider 18 18 18
Logger Provider 19 19 19
Logger Provider 20 20 20
Logger Provider 21 21 21
lp := initLoggerProvider(ctx) // slogͱOpenTelemetryͷ࿈ܞ logger := otelslog.NewLogger("my-service", otelslog.WithLoggerProvider(lp)) //
τϨʔεͱͷ࿈ܞྫ tracer := otel.Tracer("my-service") ctx, span := tracer.Start(ctx, "operation-name") defer span.End() // contextΛ͢͜ͱͰɺtraceใΛൖ͍ͯ͠Δ logger.InfoContext(ctx, "Start processing", "user_id", "12345", ) OpenTelemetry Logger Provider for Go 22 • ීஈ͍ͬͯΔ slog Λ wrap ͢Δ͚ͩ ͳΜ͔͍͍ײ͡ʹͯ͘͠ΕΔ ͲͷΑ͏ͳΈʁ
Logger Provider ͷ ઃܭͱ෦࣮ 23
Logger Provider ͷઃܭͱ෦࣮ 24 24 24
Logger Provider ͷઃܭͱ෦࣮ 25 25 25
26 // ΞϓϦέʔγϣϯ logger.InfoContext(ctx, "ॲཧ։࢝", "user_id", 123) // otelslog.Handler.Handle() func
(h *handler) Handle(ctx context.Context, r slog.Record) error { // slog.Record Λ log.Record ʹม record := convert.LogRecord(r) // ෦ͷOTel Loggerʹసૹ h.logger.Emit(ctx, record) return nil } otelslog Bridge
27 // ΞϓϦέʔγϣϯ logger.InfoContext(ctx, "ॲཧ։࢝", "user_id", 123) // otelslog.Handler.Handle() func
(h *handler) Handle(ctx context.Context, r slog.Record) error { // slog.Record Λ log.Record ʹม record := convert.LogRecord(r) // ෦ͷOTel Loggerʹసૹ h.logger.Emit(ctx, record) return nil } otelslog Bridge slog logܗ͔ࣜΒ otel logܗࣜʹ Convert
28 // ΞϓϦέʔγϣϯ logger.InfoContext(ctx, "ॲཧ։࢝", "user_id", 123) // otelslog.Handler.Handle() func
(h *handler) Handle(ctx context.Context, r slog.Record) error { // slog.Record Λ log.Record ʹม record := convert.LogRecord(r) // ෦ͷOTel Loggerʹసૹ h.logger.Emit(ctx, record) return nil } otelslog Bridge otel logger ͷ Emit Λ࣮ߦ
Logger Provider ͷઃܭͱ෦࣮ 29 29 29
30 func (l *logger) Emit(ctx context.Context, r log.Record) { newRecord
:= l.newRecord(ctx, r) for _, p := range l.provider.processors { p.OnEmit(ctx, &newRecord) } } func (l *logger) newRecord(ctx context.Context, r log.Record) Record { sc := trace.SpanContextFromContext(ctx) return Record{ body: r.Body(), severity: r.Severity(), timestamp: r.Timestamp(), traceID: sc.TraceID(), spanID: sc.SpanID(), traceFlags: sc.TraceFlags(), resource: l.provider.resource, scope: &l.instrumentationScope, } } Otel SDK
31 func (l *logger) Emit(ctx context.Context, r log.Record) { newRecord
:= l.newRecord(ctx, r) for _, p := range l.provider.processors { p.OnEmit(ctx, &newRecord) } } func (l *logger) newRecord(ctx context.Context, r log.Record) Record { sc := trace.SpanContextFromContext(ctx) return Record{ body: r.Body(), severity: r.Severity(), timestamp: r.Timestamp(), traceID: sc.TraceID(), spanID: sc.SpanID(), traceFlags: sc.TraceFlags(), resource: l.provider.resource, scope: &l.instrumentationScope, } } Otel SDK ৽ن Record ࡞
32 func (l *logger) Emit(ctx context.Context, r log.Record) { newRecord
:= l.newRecord(ctx, r) for _, p := range l.provider.processors { p.OnEmit(ctx, &newRecord) } } func (l *logger) newRecord(ctx context.Context, r log.Record) Record { sc := trace.SpanContextFromContext(ctx) return Record{ body: r.Body(), severity: r.Severity(), timestamp: r.Timestamp(), traceID: sc.TraceID(), spanID: sc.SpanID(), traceFlags: sc.TraceFlags(), resource: l.provider.resource, scope: &l.instrumentationScope, } } Otel SDK Context ͔Β Trace ID / Span ID Λ औಘͯ͠ Record ʹຒΊࠐΉ
33 func (l *logger) Emit(ctx context.Context, r log.Record) { newRecord
:= l.newRecord(ctx, r) for _, p := range l.provider.processors { p.OnEmit(ctx, &newRecord) } } func (l *logger) newRecord(ctx context.Context, r log.Record) Record { sc := trace.SpanContextFromContext(ctx) return Record{ body: r.Body(), severity: r.Severity(), timestamp: r.Timestamp(), traceID: sc.TraceID(), spanID: sc.SpanID(), traceFlags: sc.TraceFlags(), resource: l.provider.resource, scope: &l.instrumentationScope, } } Otel SDK Processor Λ ॱ࣮࣍ߦ
34 func (l *logger) Emit(ctx context.Context, r log.Record) { newRecord
:= l.newRecord(ctx, r) for _, p := range l.provider.processors { p.OnEmit(ctx, &newRecord) } } func (l *logger) newRecord(ctx context.Context, r log.Record) Record { sc := trace.SpanContextFromContext(ctx) return Record{ body: r.Body(), severity: r.Severity(), timestamp: r.Timestamp(), traceID: sc.TraceID(), spanID: sc.SpanID(), traceFlags: sc.TraceFlags(), resource: l.provider.resource, scope: &l.instrumentationScope, } } Otel SDK Processor Λ ॱ࣮࣍ߦ
35 func (l *logger) Emit(ctx context.Context, r log.Record) { newRecord
:= l.newRecord(ctx, r) for _, p := range l.provider.processors { p.OnEmit(ctx, &newRecord) } } func (l *logger) newRecord(ctx context.Context, r log.Record) Record { sc := trace.SpanContextFromContext(ctx) return Record{ body: r.Body(), severity: r.Severity(), timestamp: r.Timestamp(), traceID: sc.TraceID(), spanID: sc.SpanID(), traceFlags: sc.TraceFlags(), resource: l.provider.resource, scope: &l.instrumentationScope, } } Otel SDK Processor Λ ॱ࣮࣍ߦ
36 // SimpleProcessor func (s *SimpleProcessor) OnEmit(ctx context.Context, r *Record)
error { records := []*Record{r} return s.exporter.Export(ctx, records) } // BatchProcessor func (b *BatchProcessor) OnEmit(ctx context.Context, r *Record) error { b.queue.Enqueue(r.Clone()) return nil } Processor
37 // SimpleProcessor func (s *SimpleProcessor) OnEmit(ctx context.Context, r *Record)
error { records := []*Record{r} return s.exporter.Export(ctx, records) } // BatchProcessor func (b *BatchProcessor) OnEmit(ctx context.Context, r *Record) error { b.queue.Enqueue(r.Clone()) return nil } Processor SimpleProcessor ଈ࠲ʹ Export
38 // SimpleProcessor func (s *SimpleProcessor) OnEmit(ctx context.Context, r *Record)
error { records := []*Record{r} return s.exporter.Export(ctx, records) } // BatchProcessor func (b *BatchProcessor) OnEmit(ctx context.Context, r *Record) error { b.queue.Enqueue(r.Clone()) return nil } Processor BatchProcessor όοναΠζʹୡͨ͠Β ผͷ Goroutine Ͱ Export
Logger Provider ͷઃܭͱ෦࣮ 39 39 39
Logger Provider ͷઃܭͱ෦࣮ 40 40 40 local Ͱ otlp Ͱग़ྗͯ͠
o11y πʔϧͰ trace ͱඥ͚ͮͯ֬ೝ dev/stg/prod Ͱඪ४ग़ྗͰग़ͯ͠ӬଓԽͭͭ͠ϩάΛpipelineͰྲྀͯ֬͠ೝ
Logger Provider ͷઃܭͱ෦࣮ 41 41 41
Logger Provider ͷઃܭͱ෦࣮ 42 42 42 ͍ͭ௨Γ
Logger Provider ͷઃܭͱ෦࣮ 43 43 43 ͍ͭ௨Γ ͬͯΔLogͷܗࣜΛ OtelLogʹม
Logger Provider ͷઃܭͱ෦࣮ 44 44 44 ͍ͭ௨Γ ͬͯΔLogͷܗࣜΛ OtelLogʹม Trace
ใͷநग़ ҙͷ Export
Logger Provider ͷઃܭͱ෦࣮ 45 45 45 ͍ͭ௨Γ ͬͯΔLogͷܗࣜΛ OtelLogʹม Trace
ใͷநग़ ҙͷ Export ڥʹԠͨ֬͡ೝ
Logger Provider ͷઃܭͱ෦࣮ 46 46 46 ͍ͭ௨Γ ͬͯΔLogͷܗࣜΛ OtelLogʹม Trace
ใͷநग़ ҙͷ Export ڥʹԠͨ֬͡ೝ ͜Ε͚ͩͰ৭ʑͬͯ͘ΕΔ
·ͱΊ 47
• ϩάͱτϨʔεͷඥ͚Λউखʹͬͯ͘ΕΔ • Bridge ʹΑͬͯطଘͷϩάϥΠϒϥϦͷࠩΛٵऩ • Local Ͱ OTLP Ͱు͖ग़͢͜ͱͰɺීஈͷϩʔΧϧ։ൃͰϩάͱ
τϨʔεΛඥ͍ͮͯΈΕΔ • ҙͷมॲཧΛ processor ͱ࣮ͯ͠Ͱ͖Δ ·ͱΊ 48 48 ศརػೳ͕Γͩ͘͞ΜʂOpenTelemetry Logger Λ͍͜ͳͦ͏ʂ