contextについて(1)
- ある程度はchannelの時にやってるんですが
- いざcontextつかって良い感じにやろうと思うと
- 何が正着だっけという感じで迷うので調べ直しました
基本的なところ
- https://golang.org/pkg/context/
- https://blog.golang.org/context
- この辺をみつつ、コードを追う
Context
DeadLine
,Done
,Err
,Value
を要求するinterface
type Context interface { Deadline() (deadline time.Time, ok bool) Done() <-chan struct{} Err() error Value(key interface{}) interface{} }
context.Background()
- 最初にcontextを生成する為に呼ばれるメソッド
ctx := context.Background()
- これの正体がなんなのかというと
- contextパッケージにいるbackgroudを返している
func Background() Context { return background }
- じゃあbackgroudは何かというと
emptyCtx
がnewされた物が入っている
background = new(emptyCtx)
- emptyCtxはただのintです(型はemptyCtxなんですが)
- 要求されたメソッドはすべて実装されていますが全部偽を返します
type emptyCtx int func (*emptyCtx) Deadline() (deadline time.Time, ok bool) { return } func (*emptyCtx) Done() <-chan struct{} { return nil } func (*emptyCtx) Err() error { return nil } func (*emptyCtx) Value(key interface{}) interface{} { return nil }
- 試しにこのBackgroudで生成して
- goroutineの無限ループに渡してselectで待ち受けると
- nilが返ってくるのでブロックしているはずです
- selectについてはこちらが詳しいです
- https://www.slideshare.net/lestrrat/select-66633666
- 公式によると
- https://golang.org/ref/spec#Select_statements
- この2番目の所にblockすることが書かれています
context.WithCancel()
- cancelメソッドを返してくれる
- 要は中のdoneを操作してcancelを行っている
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { c := newCancelCtx(parent) propagateCancel(parent, &c) return &c, func() { c.cancel(true, Canceled) } }
newCancelCtx
を作成する- これは、
cancelCtx
型を返している
func newCancelCtx(parent Context) cancelCtx { return cancelCtx{Context: parent} }
- cancelCtx型は以下の定義
- Deadlineは埋め込みで回避しているはず
type cancelCtx struct { Context mu sync.Mutex // protects following fields done chan struct{} // created lazily, closed by first cancel call children map[canceler]struct{} // set to nil by the first cancel call err error // set to non-nil by the first cancel call } func (c *cancelCtx) Done() <-chan struct{} { c.mu.Lock() if c.done == nil { c.done = make(chan struct{}) } d := c.done c.mu.Unlock() return d }
- このDoneは偽が返るselectが実行されても終わらない
- 公式のここのサンプルが参考になる
- それで、最終的に
cancel
が呼ばれた際に - 内部メソッドのcancelが呼ばれる
- doneをcloseさせ、childrenにも再帰的にcancelをかける
- 最後に親からremoveして終わる
func (c *cancelCtx) cancel(removeFromParent bool, err error) { if err == nil { panic("context: internal error: missing cancel error") } c.mu.Lock() if c.err != nil { c.mu.Unlock() return // already canceled } c.err = err if c.done == nil { c.done = closedchan } else { close(c.done) } for child := range c.children { // NOTE: acquiring the child's lock while holding parent's lock. child.cancel(false, err) } c.children = nil c.mu.Unlock() if removeFromParent { removeChild(c.Context, c) } }
- closedchanが何故closedなのか最初は分からなかったが
- コードを見つけて分かった
- initでcloseしていた
var closedchan = make(chan struct{}) func init() { close(closedchan) }
- ちょいすっきりしたので気が向いたら次回につづく
objdumpを触ってみた
- objdumpというコマンドのオプションを調べてたら
- わりかし面白そうなので試して見た
--disassemble
Disassembly of section .init: 00000000000004e8 <_init>: 4e8: 48 83 ec 08 sub $0x8,%rsp 4ec: 48 8b 05 f5 0a 20 00 mov 0x200af5(%rip),%rax # 200fe8 <__gmon_start__> 4f3: 48 85 c0 test %rax,%rax 4f6: 74 02 je 4fa <_init+0x12> 4f8: ff d0 callq *%rax 4fa: 48 83 c4 08 add $0x8,%rsp 4fe: c3 retq Disassembly of section .plt: 0000000000000500 <.plt>: 500: ff 35 ba 0a 20 00 pushq 0x200aba(%rip) # 200fc0 <_GLOBAL_OFFSET_TABLE_+0x8> 506: ff 25 bc 0a 20 00 jmpq *0x200abc(%rip) # 200fc8 <_GLOBAL_OFFSET_TABLE_+0x10> 50c: 0f 1f 40 00 nopl 0x0(%rax) 0000000000000510 <puts@plt>: 510: ff 25 ba 0a 20 00 jmpq *0x200aba(%rip) # 200fd0 <puts@GLIBC_2.2.5> 516: 68 00 00 00 00 pushq $0x0 51b: e9 e0 ff ff ff jmpq 500 <.plt>
--debugging
- debug情報を表示する
- 情報量が多すぎて全部載せられない
Raw dump of debug contents of section .debug_line: Offset: 0x0 Length: 205 DWARF Version: 2 Prologue Length: 179 Minimum Instruction Length: 1 Initial value of 'is_stmt': 1 Line Base: -5 Line Range: 14 Opcode Base: 13 Opcodes: Opcode 1 has 0 args Opcode 2 has 1 arg Opcode 3 has 1 arg Opcode 4 has 1 arg Opcode 5 has 1 arg Opcode 6 has 0 args Opcode 7 has 0 args Opcode 8 has 0 args Opcode 9 has 1 arg Opcode 10 has 0 args Opcode 11 has 0 args Opcode 12 has 1 arg The Directory Table (offset 0x1b): 1 /usr/lib/gcc/x86_64-linux-gnu/7/include 2 /usr/include/x86_64-linux-gnu/bits 3 /usr/include The File Name Table (offset 0x74): Entry Dir Time Size Name 1 0 0 0 main.c 2 1 0 0 stddef.h 3 2 0 0 types.h 4 2 0 0 libio.h 5 3 0 0 stdio.h 6 2 0 0 sys_errlist.h
--source
- これがおもしろくて
- 可能であればコードと逆アセンブル結果を表示してくれる
000000000000063a <main>: #include <stdio.h> int main() { 63a: 55 push %rbp 63b: 48 89 e5 mov %rsp,%rbp printf("Hello,World\n"); 63e: 48 8d 3d 9f 00 00 00 lea 0x9f(%rip),%rdi # 6e4 <_IO_stdin_used+0x4> 645: e8 c6 fe ff ff callq 510 <puts@plt> return 0; 64a: b8 00 00 00 00 mov $0x0,%eax } 64f: 5d pop %rbp 650: c3 retq 651: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 658: 00 00 00 65b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
nmコマンドで遊んでみた
nm - オブジェクトファイルのシンボルをリストする
- https://linuxjm.osdn.jp/html/GNU_binutils/man1/nm.1.html
- このコマンドでオブジェクトファイルのシンボルをリストすることが出来る
- 割とオプションが豊富で面白いので試す
--debug-syms
#include <stdio.h> int main() { printf("Hello,World\n"); return 0; }
- このcファイルでgccを実行した場合
- オプションがある場合と無い場合でこのような差が出る
- 出ている差分はdebug用のシンボルだ
@@ -1,3 +1,29 @@ +0000000000000000 a +0000000000201010 b .bss +0000000000000000 n .comment +0000000000201000 d .data +0000000000200dc8 d .dynamic +0000000000000360 r .dynstr +00000000000002b8 r .dynsym +0000000000000730 r .eh_frame +00000000000006f0 r .eh_frame_hdr +00000000000006d4 t .fini +0000000000200dc0 t .fini_array +0000000000000298 r .gnu.hash +00000000000003e2 r .gnu.version +00000000000003f0 r .gnu.version_r +0000000000200fb8 d .got +00000000000004e8 t .init +0000000000200db8 t .init_array +0000000000000238 r .interp +0000000000000254 r .note.ABI-tag +0000000000000274 r .note.gnu.build-id +0000000000000500 t .plt +0000000000000520 t .plt.got +0000000000000410 r .rela.dyn +00000000000004d0 r .rela.plt +00000000000006e0 r .rodata +0000000000000530 t .text 0000000000200dc8 d _DYNAMIC 0000000000200fb8 d _GLOBAL_OFFSET_TABLE_ 00000000000006e0 R _IO_stdin_used @@ -25,9 +51,12 @@ 00000000000004e8 T _init 0000000000000530 T _start 0000000000201010 b completed.7696 +0000000000000000 a crtstuff.c +0000000000000000 a crtstuff.c 0000000000201000 W data_start 0000000000000560 t deregister_tm_clones 0000000000000630 t frame_dummy 000000000000063a T main +0000000000000000 a main.c U puts@@GLIBC_2.2.5 00000000000005a0 t register_tm_clones
- http://d.hatena.ne.jp/kaitoh/20060419/1145469503
- ここにnmコマンドのシンボルタイプが乗っているんだが
- この情報はどこにあるんだろうか。
-A
- ファイル名が付与される
./a.out:0000000000200dc8 d _DYNAMIC ./a.out:0000000000200fb8 d _GLOBAL_OFFSET_TABLE_ ./a.out:00000000000006e0 R _IO_stdin_used ./a.out: w _ITM_deregisterTMCloneTable ./a.out: w _ITM_registerTMCloneTable ./a.out:0000000000000834 r __FRAME_END__ ./a.out:00000000000006f0 r __GNU_EH_FRAME_HDR ./a.out:0000000000201010 D __TMC_END__ ./a.out:0000000000201010 B __bss_start ./a.out: w __cxa_finalize@@GLIBC_2.2.5 ./a.out:0000000000201000 D __data_start ./a.out:00000000000005f0 t __do_global_dtors_aux ./a.out:0000000000200dc0 t __do_global_dtors_aux_fini_array_entry ./a.out:0000000000201008 D __dso_handle ./a.out:0000000000200db8 t __frame_dummy_init_array_entry ./a.out: w __gmon_start__ ./a.out:0000000000200dc0 t __init_array_end ./a.out:0000000000200db8 t __init_array_start ./a.out:00000000000006d0 T __libc_csu_fini ./a.out:0000000000000660 T __libc_csu_init ./a.out: U __libc_start_main@@GLIBC_2.2.5 ./a.out:0000000000201010 D _edata ./a.out:0000000000201018 B _end ./a.out:00000000000006d4 T _fini ./a.out:00000000000004e8 T _init ./a.out:0000000000000530 T _start ./a.out:0000000000201010 b completed.7696 ./a.out:0000000000201000 W data_start ./a.out:0000000000000560 t deregister_tm_clones ./a.out:0000000000000630 t frame_dummy ./a.out:000000000000063a T main ./a.out: U puts@@GLIBC_2.2.5 ./a.out:00000000000005a0 t register_tm_clones
-D
- 共有ライブラリの表示
nm -D ./a.out w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable w __cxa_finalize w __gmon_start__ U __libc_start_main U puts
-g
- 外部シンボルを表示
00000000000006e0 R _IO_stdin_used w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable 0000000000201010 D __TMC_END__ 0000000000201010 B __bss_start w __cxa_finalize@@GLIBC_2.2.5 0000000000201000 D __data_start 0000000000201008 D __dso_handle w __gmon_start__ 00000000000006d0 T __libc_csu_fini 0000000000000660 T __libc_csu_init U __libc_start_main@@GLIBC_2.2.5 0000000000201010 D _edata 0000000000201018 B _end 00000000000006d4 T _fini 00000000000004e8 T _init 0000000000000530 T _start 0000000000201000 W data_start 000000000000063a T main U puts@@GLIBC_2.2.5
-u
- そのファイルで未定義なシンボルのみを表示
nm -u ./a.out w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable w __cxa_finalize@@GLIBC_2.2.5 w __gmon_start__ U __libc_start_main@@GLIBC_2.2.5 U puts@@GLIBC_2.2.5
-l
- debug情報がある場合に行数を出してくれる
000000000000063a T main /data/nm/main.c:3 U puts@@GLIBC_2.2.5 00000000000005a0 t register_tm_clones
その他
- http://shinh.skr.jp/gnu/#label:13
- ここに使い道が乗っていた
- これでリンクすべきライブラリが分かるようだ
nm -o /usr/lib/*.a | grep finding_function
gccで生成過程を眺めてみたりした
- http://www.cc.kyoto-su.ac.jp/~hxm/cstext/prog06.html
- Cで開発しているとコンパイラさんが至れり尽くせりすぎて
- liner周りの知識がもわっとするのでメモ
オブジェクトファイル生成
gcc -g -O0 -c hello.c main.c -v /usr/lib/gcc/x86_64-linux-gnu/7/cc1 -quiet -v -imultiarch x86_64-linux-gnu hello.c -quiet -dumpbase hello.c -mtune=generic -march=x86-64 -auxbase hello -g -O0 -version -fstack-protector-strong -Wformat -Wformat-security -o /tmp/cc8TEpFb.s as -v --64 -o hello.o /tmp/cc8TEpFb.s /usr/lib/gcc/x86_64-linux-gnu/7/cc1 -quiet -v -imultiarch x86_64-linux-gnu main.c -quiet -dumpbase main.c -mtune=generic -march=x86-64 -auxbase main -g -O0 -version -fstack-protector-strong -Wformat -Wformat-security -o /tmp/cc8TEpFb.s as -v --64 -o main.o /tmp/cc8TEpFb.s
実行ファイルの作成
- collect2でオブジェクトファイルを用いて実行ファイルを作成
gcc -g -O0 hello.o main.o -v /usr/lib/gcc/x86_64-linux-gnu/7/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/7/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper -plugin-opt=-fresolution=/tmp/ccxhi2PI.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/7/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/7 -L/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/7/../../.. hello.o main.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/7/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crtn.o
ヘッダーを見る
./a.out: file format elf64-x86-64 Sections: Idx Name Size VMA LMA File off Algn 0 .interp 0000001c 0000000000000238 0000000000000238 00000238 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 1 .note.ABI-tag 00000020 0000000000000254 0000000000000254 00000254 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 2 .note.gnu.build-id 00000024 0000000000000274 0000000000000274 00000274 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 3 .gnu.hash 0000001c 0000000000000298 0000000000000298 00000298 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 4 .dynsym 000000a8 00000000000002b8 00000000000002b8 000002b8 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 5 .dynstr 00000082 0000000000000360 0000000000000360 00000360 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 6 .gnu.version 0000000e 00000000000003e2 00000000000003e2 000003e2 2**1 CONTENTS, ALLOC, LOAD, READONLY, DATA 7 .gnu.version_r 00000020 00000000000003f0 00000000000003f0 000003f0 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 8 .rela.dyn 000000c0 0000000000000410 0000000000000410 00000410 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 9 .rela.plt 00000018 00000000000004d0 00000000000004d0 000004d0 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 10 .init 00000017 00000000000004e8 00000000000004e8 000004e8 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 11 .plt 00000020 0000000000000500 0000000000000500 00000500 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE 12 .plt.got 00000008 0000000000000520 0000000000000520 00000520 2**3 CONTENTS, ALLOC, LOAD, READONLY, CODE 13 .text 000001b2 0000000000000530 0000000000000530 00000530 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE 14 .fini 00000009 00000000000006e4 00000000000006e4 000006e4 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 15 .rodata 00000010 00000000000006f0 00000000000006f0 000006f0 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 16 .eh_frame_hdr 00000044 0000000000000700 0000000000000700 00000700 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 17 .eh_frame 00000128 0000000000000748 0000000000000748 00000748 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA 18 .init_array 00000008 0000000000200db8 0000000000200db8 00000db8 2**3 CONTENTS, ALLOC, LOAD, DATA 19 .fini_array 00000008 0000000000200dc0 0000000000200dc0 00000dc0 2**3 CONTENTS, ALLOC, LOAD, DATA 20 .dynamic 000001f0 0000000000200dc8 0000000000200dc8 00000dc8 2**3 CONTENTS, ALLOC, LOAD, DATA 21 .got 00000048 0000000000200fb8 0000000000200fb8 00000fb8 2**3 CONTENTS, ALLOC, LOAD, DATA 22 .data 00000010 0000000000201000 0000000000201000 00001000 2**3 CONTENTS, ALLOC, LOAD, DATA 23 .bss 00000008 0000000000201010 0000000000201010 00001010 2**0 ALLOC 24 .comment 0000002a 0000000000000000 0000000000000000 00001010 2**0 CONTENTS, READONLY 25 .debug_aranges 00000060 0000000000000000 0000000000000000 0000103a 2**0 CONTENTS, READONLY, DEBUGGING 26 .debug_info 00000644 0000000000000000 0000000000000000 0000109a 2**0 CONTENTS, READONLY, DEBUGGING 27 .debug_abbrev 000001d4 0000000000000000 0000000000000000 000016de 2**0 CONTENTS, READONLY, DEBUGGING 28 .debug_line 000001a2 0000000000000000 0000000000000000 000018b2 2**0 CONTENTS, READONLY, DEBUGGING 29 .debug_str 00000290 0000000000000000 0000000000000000 00001a54 2**0 CONTENTS, READONLY, DEBUGGING
rustさわってみた(2)
- コンパイラに推論させるとどの型になるのか気になった
i32
になるようだ。- そのほかには型の最大値と最小値がどう取れるかみた。
fn main() { let v = 5; println!("x is {}",v); let u8_min:u8 = std::u8::MIN; println!("u8 min: {}",u8_min); let u8_max:u8 = std::u8::MAX; println!("u8 max: {}",vu8_max); }
cmakeさわってみた(1)
- clion触っていると必要になるので調査
- https://cmake.org/cmake-tutorial/
- https://qiita.com/shohirose/items/45fb49c6b429e8b204ac
- ここの記述が分かりやすい
ファイルを用意
#include <stdio.h> int main(int argc, char *argv[]) { printf("hello world\n"); return 0; }
cmake_minimum_required(VERSION 2.8) project(hoge) add_executable(a.out main.c)
実行
mkdir build cd build cmake .. -- The C compiler identification is GNU 7.3.0 -- The CXX compiler identification is GNU 7.3.0 -- Check for working C compiler: /usr/bin/cc -- Check for working C compiler: /usr/bin/cc -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Detecting C compile features -- Detecting C compile features - done -- Check for working CXX compiler: /usr/bin/c++ -- Check for working CXX compiler: /usr/bin/c++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done -- Generating done -- Build files have been written to: /data/cmake/build
結果
- buildディレクトリに以下のファイルが生成される
build |-- CMakeCache.txt |-- CMakeFiles | |-- 3.10.2 | | |-- CMakeCCompiler.cmake | | |-- CMakeCXXCompiler.cmake | | |-- CMakeDetermineCompilerABI_C.bin | | |-- CMakeDetermineCompilerABI_CXX.bin | | |-- CMakeSystem.cmake | | |-- CompilerIdC | | | |-- CMakeCCompilerId.c | | | |-- a.out | | | `-- tmp | | `-- CompilerIdCXX | | |-- CMakeCXXCompilerId.cpp | | |-- a.out | | `-- tmp | |-- CMakeDirectoryInformation.cmake | |-- CMakeOutput.log | |-- CMakeTmp | |-- Makefile.cmake | |-- Makefile2 | |-- TargetDirectories.txt | |-- a.out.dir | | |-- DependInfo.cmake | | |-- build.make | | |-- cmake_clean.cmake | | |-- depend.make | | |-- flags.make | | |-- link.txt | | `-- progress.make | |-- cmake.check_cache | |-- feature_tests.bin | |-- feature_tests.c | |-- feature_tests.cxx | `-- progress.marks |-- Makefile `-- cmake_install.cmake 8 directories, 29 files
- 基本的な使い方は分かった
- あとは、静的ライブラリを作成する方法を後日やる
OpenCensusについて調べてみた
OpenCensusとは
- https://opencensus.io/
- サービスからメトリクスと配布トレースを収集する単一のライブラリ
- 各言語のライブラリが出ているが今回はGoを調べる
- サポートされているバックエンドも多い
- 所謂
分散トレーシングシステム
へ格納する- Azure Monitor、Datadog、Instana、Jaeger、SignalFX、Stackdriver、およびZipkin
分散トレーシングシステムとは
2種類のアプローチがある
- Black-box schemes
- Annotation-based schemes
- 特定のリクエストを分析することがでる
トレースID
を発行することによりログを追跡を可能にするスパンID
を使用することによりログの親子関係を識別可能にする
- 特定のリクエストを分析することがでる
- 今回対象にしているのは後者の
Annotation-based schemes
の方
取得データ
この2種類がある。
Trace
- https://opencensus.io/quickstart/go/tracing/
- ここにサンプルがある
git clone https://github.com/opencensus-otherwork/opencensus-quickstarts cd opencensus-quickstarts/go/tracing-to-zipkin go get go.opencensus.io/* && go get go.opencensus.io/exporter/zipkin # zipkinのインストール curl -sSL https://zipkin.io/quickstart.sh | bash -s # zipkin起動 java -jar zipkin.jar
- サンプルを実行して以下へアクセス
- 各Spanとそれにかかった処理時間等が表示される
サンプルの内容
- サンプルは以下の内容が実行される
1. Configure exporter to export traces to Zipkin. 2. Configure 100% sample rate, otherwise, few traces will be sampled. 3. Create a span with the background context, making this the parent span. 4. Start a child span. This will be a child span because we've passed 5. Make the span close at the end of this function. 6. Set status upon error 7. Annotate our span to capture metadata about our operation
traceへのexporterの登録
traceへ生成したexporterを登録している
trace.RegisterExporter(ze)
- このopencensusは設計上複数のexporterが持てるので
exportersMap
へexporterを登録している
func RegisterExporter(e Exporter) { exporterMu.Lock() new := make(exportersMap) if old, ok := exporters.Load().(exportersMap); ok { for k, v := range old { new[k] = v } } new[e] = struct{}{} exporters.Store(new) exporterMu.Unlock() }
traceのサンプルレート
- このtraceのconfigへセットしている
DefaultSampler
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
これはsetIsSampled
で収集対象にするかに使用されている
span.spanContext.setIsSampled(sampler(SamplingParameters{ ParentContext: parent, TraceID: span.spanContext.TraceID, SpanID: span.spanContext.SpanID, Name: name, HasRemoteParent: remoteParent}).Sample)
ここを遡っていくとatomic
が出てくる
func (sc *SpanContext) setIsSampled(sampled bool) { if sampled { sc.TraceOptions |= 1 } else { sc.TraceOptions &= ^TraceOptions(1) } }
- このあたりが詳しいです
- 要約すると演算をatomicにする為の処理です
出力結果
- 各処理の経過時間が取れている
- stackdriver/traceの方を使用すると割と詳しい内容が出る