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
Shota Iwami
July 23, 2025
Technology
2.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
1.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.6k
feature flag と OpenTelemetry
biwashi
7
2.5k
OpenFeatureと自動生成を活用したフィーチャーフラグの宣言的集約管理
biwashi
20
7.6k
Unified Diff 形式の差分から Go AST を構築して feature flag を自動計装する
biwashi
11
1.6k
Other Decks in Technology
See All in Technology
Podは生きているのにGoだけが落ちる:GOGCとGOMEMLIMITで追うInvisible OOM Killの謎
tkc66buzz
1
500
クロスボーダーM&AのValue Upを支えるプロダクト開発。日米チームのハブになったプロダクトエンジニアの実践 / Product Engineering Conference 2026
genda
0
110
AI活用の現在地、 ちゃんと見えてますか?/XPfest-2026
visional_engineering_and_design
0
180
AIで仕事のやり方を変える
matsu7874
3
1k
module Synths; end
asonas
1
130
株式会社シーエーシー エンジニア向け会社紹介資料
cac
0
57k
10分で知る最近のOmarchy
komagata
0
240
OpenTelemetry eBPF Instrumentationの舞台裏 / Behind the Scenes of OpenTelemetry eBPF Instrumentation
ymotongpoo
3
960
Snowflakeのコスト最適化を支えるアーキテクチャ設計
ktatsuya
0
1.4k
AIで実装は速くなった。なのにプロダクトは速くならない。職能の壁を越えて価値のフローを設計する
nwiizo
8
7.7k
AIオーケストレーションを活用した 開発ワークフローの設計と実践
bqnq
0
130
2026-09-11 【Snowflake World Tour Tokyo 2026】Snowflakeを起点に、AI Agentが自律稼働し続ける未来へ / Driving AI Agents with Snowflake
civitaspo
0
280
Featured
See All Featured
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
270
Raft: Consensus for Rubyists
vanstee
141
7.7k
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
680
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
560
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
490
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.3k
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
440
The browser strikes back
jonoalderson
0
1.7k
Documentation Writing (for coders)
carmenintech
77
5.5k
The Cost Of JavaScript in 2023
addyosmani
55
10k
Rails Girls Zürich Keynote
gr2m
96
14k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
450
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 Λ͍͜ͳͦ͏ʂ