Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
OpenTelemetry の Log を使いこなそう
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Shota Iwami
July 23, 2025
Technology
2.3k
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
1.1k
Monorepo Error Management: Automated Runbooks and Team-Targeted Alert Distribution
biwashi
2
1.2k
スタートアップ創業期を支えるオブザーバビリティ基盤のこれまでとこれから
biwashi
10
1.8k
モノレポ開発のエラー、誰が見る?Datadog で実現する適切なトリアージとエスカレーション
biwashi
7
1.9k
k6を活用した再現性・拡張性の高い負荷試験基盤の構築
biwashi
13
4.4k
Datadogマニアック機能活用術
biwashi
7
4.8k
feature flag と OpenTelemetry
biwashi
7
2.5k
OpenFeatureと自動生成を活用したフィーチャーフラグの宣言的集約管理
biwashi
20
7.7k
Unified Diff 形式の差分から Go AST を構築して feature flag を自動計装する
biwashi
11
1.6k
Other Decks in Technology
See All in Technology
AI時代のAPI開発を加速する品質ガードレール / API Quality Guardrails in the AI Era
yokawasa
0
150
調査タスクをAIと乗り切る 〜過去の調査をナレッジ化し 調査手順をスキルにする〜
mot_techtalk
1
120
AI時代に必要な脅威モデリング― 変化の速度に負けない理解とリスク判断
masakane55
4
1.1k
FinTech 1-2 : Overview of FinTech
ks91
PRO
0
150
[2026 Oracle Technical Deep Dive] AI時代のアプリケーションを支えるCloud NativeとJava EEモダナイゼーション (2026年9月17日開催)
oracle4engineer
PRO
0
120
[2026 Oracle Technical Deep Dive] AI時代のデータベース基盤をどう選ぶ? Exadata Database Serviceの選択肢と使い分け (2026年9月17日開催)
oracle4engineer
PRO
0
230
おそらく日本で唯一のDevRelインターン生として
husengs7
0
170
組み立てて楽しむ AWS Blocks 入門
kmiya84377
0
220
1万名の社員が使う認証基盤で どう信頼性を担保するか?
kairim0
0
210
実体験から学ぶ分析エージェントの開発と運⽤
recruitengineers
PRO
1
210
freeeらしさをAIとともに作る / Creating the freee Experience with AI
ymrl
0
200
The seven pitfalls of AI (revised version)
ufried
0
270
Featured
See All Featured
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
700
Building AI with AI
inesmontani
PRO
1
1.3k
Why You Should Never Use an ORM
jnunemaker
PRO
61
10k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
Testing 201, or: Great Expectations
jmmastey
46
8.3k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
203
76k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2.1k
GitHub's CSS Performance
jonrohan
1033
470k
Chasing Engaging Ingredients in Design
codingconduct
0
340
The Anti-SEO Checklist Checklist. Pubcon Cyber Week
ryanjones
0
260
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
540
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 Λ͍͜ͳͦ͏ʂ