雑なメモ書き

気楽にいきます

contextについて(1)

  • ある程度はchannelの時にやってるんですが
  • いざ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
}

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 - オブジェクトファイルのシンボルをリストする

--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

-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

その他

nm -o /usr/lib/*.a | grep finding_function

gccで生成過程を眺めてみたりした

オブジェクトファイル生成

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

ヘッダーを見る

  • objdumpでheaderを見るとこんな感じ
  • macコンパイルした方が少ない
  • elf形式であること
  • headerのセクションが分かれていることがわかる
./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)

ファイルを用意

#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
|-- 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

分散トレーシングシステムとは

  • https://techlife.cookpad.com/entry/2017/09/06/115710

  • 2種類のアプローチがある

    • Black-box schemes
    • Annotation-based schemes
      • 特定のリクエストを分析することがでる
        • トレースIDを発行することによりログを追跡を可能にする
        • スパンIDを使用することによりログの親子関係を識別可能にする
  • 今回対象にしているのは後者のAnnotation-based schemesの方

取得データ

この2種類がある。

Trace

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)
    }
}

出力結果

  • 各処理の経過時間が取れている
  • stackdriver/traceの方を使用すると割と詳しい内容が出る

f:id:hiroyukim:20190310114104p:plain