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
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Shota Iwami
July 23, 2025
Technology
2.1k
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.2k
スタートアップ創業期を支えるオブザーバビリティ基盤のこれまでとこれから
biwashi
10
1.7k
モノレポ開発のエラー、誰が見る?Datadog で実現する適切なトリアージとエスカレーション
biwashi
7
1.8k
k6を活用した再現性・拡張性の高い負荷試験基盤の構築
biwashi
13
4.4k
Datadogマニアック機能活用術
biwashi
7
4.5k
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
AI for Science時代を切り開く、政府の次世代HPC戦略の展望
gpuunite_official
0
210
あなたの知らないバージョン命名規則
sat
PRO
2
120
カーネルまで探検して理解するふたつの自動計装
sumiyae
0
160
2026-08-15 JAWS-UG 茨城 #16 Secrets ManagerにおけるSecret値の管理(Terraformの場合) / Secrets Manager Secrets
masasuzu
0
520
Go 1.27 の標準パッケージに uuid が入った!のでいろいろ喋る / go_127_std_go_uuid
convto
3
590
Oracle MCP Servers Explained
thatjeffsmith
0
410
Head First モブプログラミング / Head First Mobprogramming
takaking22
10
12k
Invisible to AI? Making TYPO3 Sites Quotable by AI Search Systems
wolfgangwagner
0
240
20260817_生成AIの動向と中学校・高等学校での活用を考える_v1.00_公開用
doradora09
PRO
0
190
AIコーディングの次。コードレビューと理解負荷を解消して組織の開発生産性を高める
moongift
PRO
2
2.7k
地震情報アプリを作ってみた
yama3133
1
110
AIペネトレーションテスト・ セキュリティ検証「AgenticSec」紹介資料
laysakura
2
9.4k
Featured
See All Featured
エンジニアに許された特別な時間の終わり
watany
108
250k
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
250
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
420
Utilizing Notion as your number one productivity tool
mfonobong
4
550
How to build a perfect <img>
jonoalderson
1
5.9k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
4 Signs Your Business is Dying
shpigford
187
23k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
1
2.8k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
10k
We Are The Robots
honzajavorek
0
300
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
210
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
800
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 Λ͍͜ͳͦ͏ʂ