<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Blogs on /dev/anil</title><link>https://anxl.dev/blog/</link><description>Recent content in Blogs on /dev/anil</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><copyright>© 2021 Anıl Mısırlıoğlu</copyright><lastBuildDate>Wed, 23 Jun 2021 12:00:00 +0300</lastBuildDate><atom:link href="https://anxl.dev/blog/index.xml" rel="self" type="application/rss+xml"/><item><title>Docker Görüntünüzün Boyutunu Minimize Edin</title><link>https://anxl.dev/blog/minify-docker-image/</link><pubDate>Wed, 23 Jun 2021 12:00:00 +0300</pubDate><guid>https://anxl.dev/blog/minify-docker-image/</guid><description>CI/CD gibi süreçlerimizi hızlandırmak için Docker Image boyutlarımızı minimize etmek önemlidir. Bu yazımızda basit bir Go uygulaması yazıp, hem Go&amp;rsquo;yu hem de Docker&amp;rsquo;ı optimize ederek 4 adımda Image boyutumuzu neredeyse 1GB&amp;rsquo;dan 1 MB&amp;rsquo;a kadar düşüreceğiz.
Ön Hazırlık package main import ( &amp;#34;fmt&amp;#34; &amp;#34;net/http&amp;#34; ) func main() { http.HandleFunc(&amp;#34;/&amp;#34;, func (w http.ResponseWriter, _ *http.Request) { fmt.Fprintf(w, &amp;#34;Hello World&amp;#34;) }) http.ListenAndServe(&amp;#34;:80&amp;#34;, nil) } Burada basit bir HTTP server başlatan 10 satırlık Go programı yazdık.</description><content>&lt;p>CI/CD gibi süreçlerimizi hızlandırmak için Docker Image boyutlarımızı minimize etmek önemlidir. Bu yazımızda basit bir
Go uygulaması yazıp, hem Go&amp;rsquo;yu hem de Docker&amp;rsquo;ı optimize ederek 4 adımda Image boyutumuzu neredeyse 1GB&amp;rsquo;dan 1 MB&amp;rsquo;a kadar düşüreceğiz.&lt;/p>
&lt;hr>
&lt;h3 id="preliminary">Ön Hazırlık&lt;/h3>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-go" data-lang="go">&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;span style="color:#f92672">import&lt;/span> (
&lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;span style="color:#e6db74">&amp;#34;net/http&amp;#34;&lt;/span>
)
&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">HandleFunc&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;/&amp;#34;&lt;/span>, &lt;span style="color:#66d9ef">func&lt;/span> (&lt;span style="color:#a6e22e">w&lt;/span> &lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">ResponseWriter&lt;/span>, &lt;span style="color:#a6e22e">_&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">Request&lt;/span>) {
&lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprintf&lt;/span>(&lt;span style="color:#a6e22e">w&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;Hello World&amp;#34;&lt;/span>)
})
&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">ListenAndServe&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;:80&amp;#34;&lt;/span>, &lt;span style="color:#66d9ef">nil&lt;/span>)
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Burada basit bir HTTP server başlatan 10 satırlık Go programı yazdık. Şimdi bunu adım adım Container haline getirelim.&lt;/p>
&lt;hr>
&lt;h3 id="step-1">Adım 1 - Yeni Bir Başlangıç&lt;/h3>
&lt;p>Öncelikle yazabileceğimiz en kötü Dockerfile&amp;rsquo;ı yazalım. Burada kısaca golang 1.16 image&amp;rsquo;ını kullanıyoruz ve uygulamamızı
build edip entrypoint olarak belirtiyoruz.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span style="color:#66d9ef">FROM&lt;/span>&lt;span style="color:#e6db74"> golang:1.16&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">WORKDIR&lt;/span>&lt;span style="color:#e6db74"> /app&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">COPY&lt;/span> . .&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">RUN&lt;/span> go build -o /bin/blog-app&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">ENTRYPOINT&lt;/span> [&lt;span style="color:#e6db74">&amp;#34;/bin/blog-app&amp;#34;&lt;/span>]&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Build Sonucu Image Boyutu:&lt;/strong> &lt;code>868 MB&lt;/code>&lt;/p>
&lt;p>Bu iyi bir image değil, boyutu gereksiz büyük. Bunu optimize etmeye başlayalım.&lt;/p>
&lt;hr>
&lt;h3 id="step-2">Adım 2 - Minimalizm Bazen İyidir&lt;/h3>
&lt;p>Şimdi yazdığımız bu Dockerfile&amp;rsquo;ı biraz daha optimize edelim ve alpine image&amp;rsquo;ı kullanalım. Bilmiyorsanız Alpine, image&amp;rsquo;ın
boyutunu düşürmek için biçilmiş bir kaftandır, çünkü içerisinde temel os runtime&amp;rsquo;ları dışında pek bir binary yoktur.
Buradan üstteki yaptıklarımızdan farklı olarak sadece ana image&amp;rsquo;ımızı Alpine olarak değiştiriyoruz.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span style="color:#66d9ef">FROM&lt;/span>&lt;span style="color:#e6db74"> golang:1.16-alpine&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">WORKDIR&lt;/span>&lt;span style="color:#e6db74"> /app&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">COPY&lt;/span> . .&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">RUN&lt;/span> go build -o /bin/blog-app&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">ENTRYPOINT&lt;/span> [&lt;span style="color:#e6db74">&amp;#34;/bin/blog-app&amp;#34;&lt;/span>]&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Build Sonucu Image Boyutu:&lt;/strong> &lt;code>308 MB&lt;/code> ~(-500MB)&lt;/p>
&lt;p>Gördüğünüz gibi Alpine image&amp;rsquo;ına geçerek yaklaşık 500 MB tasarruf sağladık.&lt;/p>
&lt;hr>
&lt;h3 id="step-3">Adım 3 - Multi-Stage Build&lt;/h3>
&lt;p>Go&amp;rsquo;nun güzel özelliklerinden biride static build alabilmenizdir. Yani Go programınızın çalışması için &lt;code>libc&lt;/code> gibi bağımlılıklara
ihtiyaç duymadan çalışabilir. Burada artık multi-stage build dediğimiz yapıya geçiyoruz. Yani build&amp;rsquo;imizi Alpine image&amp;rsquo;ımızda
yapıp, aldığımız build&amp;rsquo;i &lt;code>scratch&lt;/code> dediğimiz boş bir image içerisine kopyalayıp orada çalıştırıyoruz.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span style="color:#75715e">### Stage 1&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">FROM&lt;/span>&lt;span style="color:#e6db74"> golang:1.16-alpine AS builder&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">WORKDIR&lt;/span>&lt;span style="color:#e6db74"> /app&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">COPY&lt;/span> . .&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">RUN&lt;/span> CGO_ENABLED&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">0&lt;/span> GOOS&lt;span style="color:#f92672">=&lt;/span>linux go build -ldflags &lt;span style="color:#e6db74">&amp;#34;-s -w&amp;#34;&lt;/span> -o /app/blog-app&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#75715e">### Stage 2&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">FROM&lt;/span>&lt;span style="color:#e6db74"> scratch&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">COPY&lt;/span> --from&lt;span style="color:#f92672">=&lt;/span>builder /app/blog-app /bin/blog-app&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">ENTRYPOINT&lt;/span> [&lt;span style="color:#e6db74">&amp;#34;/bin/blog-app&amp;#34;&lt;/span>]&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Build Sonucu Image Boyutu:&lt;/strong> &lt;code>4.42 MB&lt;/code> ~(-300MB)&lt;/p>
&lt;p>Burada ise multi-stage build ile boş bir image&amp;rsquo;a geçerek 300 MB tasarruf sağlamış olduk. Yani sadece build ettiğimiz
binary&amp;rsquo;nin boyutu kalıyor geriye. Hadi bunuda optimize edelim.&lt;/p>
&lt;hr>
&lt;h3 id="step-4">Adım 4 - UPX&lt;/h3>
&lt;p>Artık son adıma geldik. Burada ise &lt;a href="https://github.com/upx/upx">UPX&lt;/a> kullanarak build ettiğimiz static binary&amp;rsquo;i daha da
minify edelim.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span style="color:#75715e">### Stage 1&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">FROM&lt;/span>&lt;span style="color:#e6db74"> golang:1.16-alpine AS builder&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">WORKDIR&lt;/span>&lt;span style="color:#e6db74"> /app&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">COPY&lt;/span> . .&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">RUN&lt;/span> CGO_ENABLED&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">0&lt;/span> GOOS&lt;span style="color:#f92672">=&lt;/span>linux go build -ldflags &lt;span style="color:#e6db74">&amp;#34;-s -w&amp;#34;&lt;/span> -o /app/blog-app&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">RUN&lt;/span> apk add upx&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">RUN&lt;/span> upx --ultra-brute /app/blog-app&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#75715e">### Stage 2&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">FROM&lt;/span>&lt;span style="color:#e6db74"> scratch&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">COPY&lt;/span> --from&lt;span style="color:#f92672">=&lt;/span>builder /app/blog-app /bin/blog-app&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">ENTRYPOINT&lt;/span> [&lt;span style="color:#e6db74">&amp;#34;/bin/blog-app&amp;#34;&lt;/span>]&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Build Sonucu Image Boyutu:&lt;/strong> &lt;code>1.32 MB&lt;/code> ~(-3MB)&lt;/p>
&lt;p>Binary&amp;rsquo;mizide minify ettik ve 3 MB bir tasarruf sağlayarak image boyutumuzu 1 MB&amp;rsquo;a kadar indirmiş olduk. Unutmayın bu
adımdaki boyut değişimi, sizin programızında ne kadar paket kullandığınıza ve ne kadar kod bulunduğa bağlı olarak
değişebilir. Yani go build&amp;rsquo;i 100 MB çıkıyor ise UPX ile bunu 30 MB&amp;rsquo;a düşürebilirsiniz.&lt;/p>
&lt;hr>
&lt;h2 id="result">Sonuç&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>REPOSITORY&lt;/th>
&lt;th>TAG&lt;/th>
&lt;th>IMAGE ID&lt;/th>
&lt;th>SIZE&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>blog&lt;/td>
&lt;td>step-1&lt;/td>
&lt;td>d96961d177b7&lt;/td>
&lt;td>868MB&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>blog&lt;/td>
&lt;td>step-2&lt;/td>
&lt;td>7c874d66fd2d&lt;/td>
&lt;td>308MB&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>blog&lt;/td>
&lt;td>step-3&lt;/td>
&lt;td>92e68959939e&lt;/td>
&lt;td>4.42MB&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>blog&lt;/td>
&lt;td>step-4&lt;/td>
&lt;td>0a753fc54c4c&lt;/td>
&lt;td>1.32MB&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Günün sonunda yukarıdaki gibi bir tablo karşımıza çıkıyor. Optimizasyonlar ile birlikte image boyutumuzu &lt;strong>868 MB&lt;/strong>&amp;lsquo;dan
&lt;strong>1.32 MB&lt;/strong>&amp;lsquo;a düşürmüş oluyoruz. Tabiki burada unutmamız gereken bazı maddeler var.&lt;/p>
&lt;ul>
&lt;li>Image boyutu programınızın performansını etkilemez, ama bir çok süreci hızlandırabilir.&lt;/li>
&lt;li>Eğer programınızın os veya paket bağımlılıkları varsa bunları Dockerfile&amp;rsquo;a eklemeniz gerekir ve boyutu küçülteyim derken
anlaması zor complex bir Dockerfile üretebilirsiniz.&lt;/li>
&lt;li>UPX her durumda gerekli olmayabilir, burada dikkat etmeniz gereken nokta sizin ne kadarlık bir boyuta kadar bunu
tolere edebileceğiniz.&lt;/li>
&lt;/ul>
&lt;p>Umarım bu yazı sizin için faydalı olmuştur, bir sonraki yazılarda görüşmek üzere.&lt;/p></content></item><item><title>Bash Tricks</title><link>https://anxl.dev/blog/bash-tricks/</link><pubDate>Sun, 13 Jun 2021 12:00:00 +0300</pubDate><guid>https://anxl.dev/blog/bash-tricks/</guid><description>Bash bir yazılımcı için isviçre çakısı gibidir, ve bunu efektif kullanabilmek oldukça önemlidir. Bash&amp;rsquo;i efektif kullanabilmek için birbirinden güzel 15 bash tekniği.
Sihirli Parantezler 1- Eğer bir dosyanın uzantısını değiştirmek istiyorsanız uzun uzun yazmak yerine, iki süslü parantez koyarak bu sorunu hemen ortadan kaldırabilirsiniz.
&amp;gt;&amp;gt; mv ./file.{html,md} 2- Veya bir sayı kümesi oluşturup bunu iterate edebilirsiniz.
&amp;gt;&amp;gt; echo {1..3} # {START..END..INCREMENT} pattern for i in {0..7..2} do; echo &amp;#34;for loop n: $i&amp;#34;; done Klasör İşlemleri 3- Genelde oluşturduğumuz dosyaların içine girmemiz gerekir.</description><content>&lt;p>Bash bir yazılımcı için isviçre çakısı gibidir, ve bunu efektif kullanabilmek oldukça önemlidir. Bash&amp;rsquo;i efektif
kullanabilmek için birbirinden güzel 15 bash tekniği.&lt;/p>
&lt;hr>
&lt;h2 id="magical-brackets">Sihirli Parantezler&lt;/h2>
&lt;p>&lt;strong>1-&lt;/strong> Eğer bir dosyanın uzantısını değiştirmek istiyorsanız uzun uzun yazmak yerine, iki süslü parantez koyarak bu sorunu
hemen ortadan kaldırabilirsiniz.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">&amp;gt;&amp;gt; mv ./file.&lt;span style="color:#f92672">{&lt;/span>html,md&lt;span style="color:#f92672">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>2-&lt;/strong> Veya bir sayı kümesi oluşturup bunu iterate edebilirsiniz.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">&amp;gt;&amp;gt; echo &lt;span style="color:#f92672">{&lt;/span>1..3&lt;span style="color:#f92672">}&lt;/span>
&lt;span style="color:#75715e"># {START..END..INCREMENT} pattern&lt;/span>
&lt;span style="color:#66d9ef">for&lt;/span> i in &lt;span style="color:#f92672">{&lt;/span>0..7..2&lt;span style="color:#f92672">}&lt;/span>
&lt;span style="color:#66d9ef">do&lt;/span>;
echo &lt;span style="color:#e6db74">&amp;#34;for loop n: &lt;/span>$i&lt;span style="color:#e6db74">&amp;#34;&lt;/span>;
&lt;span style="color:#66d9ef">done&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="directory-operations">Klasör İşlemleri&lt;/h2>
&lt;p>&lt;strong>3-&lt;/strong> Genelde oluşturduğumuz dosyaların içine girmemiz gerekir. Ve bunu 2 komut girerek yapmaktansa kendimiz bir fonksiyon
yazarak tek komuta indirebiliriz.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">&lt;span style="color:#75715e"># bunu fonksiyonlarınızın olduğu dosyanın içine yapıştırın&lt;/span>
mcd&lt;span style="color:#f92672">(){&lt;/span>
mkdir -p &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>1:?Need to specify an argument&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> cd &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$1&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;span style="color:#f92672">}&lt;/span>
&amp;gt;&amp;gt; mcd test
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>4-&lt;/strong> Özellikle Java, C# gibi dillerle yazılan projelerde çok derin bir klasörleme olabiliyor ve bir süre sonra &lt;code>root&lt;/code> dizine
gitmek epeyce zorlaşabilir. Bunun için bir &lt;code>alias&lt;/code> tanımlayarak hızlı bir şekilde projelerinizin root dizinine
gidebilirsiniz.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">&lt;span style="color:#75715e"># bunu alias&amp;#39;larınızı tanımladığınız dosyanın içine yerleştirin&lt;/span>
&lt;span style="color:#75715e"># not: sadece git ile çalışılan projelerde çalışır&lt;/span>
alias cdr&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#39;cd $(git rev-parse --show-toplevel)&amp;#39;&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>5-&lt;/strong> Bir önceki bulunduğunuz konumamı gitmek istiyorsunuz? O halde bir &lt;code>-&lt;/code> ile bu sorunu çözebilirsiniz.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">&amp;gt;&amp;gt; cd -
&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="semboller">Semboller&lt;/h2>
&lt;p>&lt;strong>6-&lt;/strong> Her yerde olduğu gibi değişkenler bash&amp;rsquo;dede önemlidir. &lt;code>$( )&lt;/code> sembolleri arasına yazdığınız karakterler bash&amp;rsquo;de
değişken olarak yorumlanır.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">&amp;gt;&amp;gt; touch foo-&lt;span style="color:#66d9ef">$(&lt;/span>date -I&lt;span style="color:#66d9ef">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>7-&lt;/strong> Bir işlem yapıcaksınız ve bu işlemin çok uzun süreceğini mi düşünüyorsunuz? O halde bu işlemi arka planda çalıştırmak
oldukça mantıklı olur. Komutunuzun sonuna &lt;code>&amp;amp;&lt;/code> işareti ekleyerek işlemin arka planda çalışmasını sağlayabilir ve işinize
kaldığınız yerden devam edebilirsiniz.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">&amp;gt;&amp;gt; curl --upload-file ./hello.txt https://transfer.sh/hello.txt &amp;amp;
-- OUTPUT --
&lt;span style="color:#f92672">[&lt;/span>1&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#ae81ff">1564&lt;/span>
&lt;span style="color:#f92672">[&lt;/span>1&lt;span style="color:#f92672">]&lt;/span> + &lt;span style="color:#ae81ff">1564&lt;/span> &lt;span style="color:#66d9ef">done&lt;/span> curl --upload-file ./default.md https://transfer.sh/default.md
&lt;span style="color:#75715e"># eğer işlem devam ederken, işlemi öldürmek isterseniz; kill [process id]&lt;/span>
&amp;gt;&amp;gt; kill &lt;span style="color:#ae81ff">1564&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>8-&lt;/strong> Örneğin üstteki örneğimizde ki gibi işlemi arka plana aldınız ve process id&amp;rsquo;sini unuttunuz. &lt;code>$!&lt;/code> en son yürüttüğünüz
arka plan işleminin ID&amp;rsquo;sini size vericektir.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">&amp;gt;&amp;gt; sleep &lt;span style="color:#ae81ff">60&lt;/span> &amp;amp;
&lt;span style="color:#f92672">[&lt;/span>1&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#ae81ff">1814&lt;/span>
&amp;gt;&amp;gt; kill $!
&lt;span style="color:#f92672">[&lt;/span>1&lt;span style="color:#f92672">]&lt;/span> + &lt;span style="color:#ae81ff">1814&lt;/span> terminated sleep &lt;span style="color:#ae81ff">60&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>9-&lt;/strong> Son yazdığınız komutu tekrar mı yazmanız gerekiyor? O halde &lt;code>!!&lt;/code> yazarak son yazılan komutu tekrar alabilirsiniz.&lt;/p>
&lt;p>&lt;strong>NOT:&lt;/strong> Aslında Terminal emülatörlerinde ileri geri tuşları ile bu daha kolay bir şekilde yapılabiliyor fakat Bash
Script yazıyorsanız böyle bir imkanınız olmaz ve son komutu bu şekilde almak zorunda kalırsınız.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">&amp;gt;&amp;gt; echo Hello World
Hello World
&amp;gt;&amp;gt; !!
-- RESULT --
&amp;gt;&amp;gt; echo Hello World
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>10-&lt;/strong> Peki komutu değilde son parametrelerini almak istiyorsak? Bu durumda ise &lt;code>!$&lt;/code> yardımımıza yetişiyor.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">&amp;gt;&amp;gt; echo &lt;span style="color:#e6db74">&amp;#34;Hello World&amp;#34;&lt;/span>
Hello World
&amp;gt;&amp;gt; test !$
-- RESULT --
&amp;gt;&amp;gt; test &lt;span style="color:#e6db74">&amp;#34;Hello World&amp;#34;&lt;/span>
&lt;span style="color:#75715e"># farklı kullanımlar; &lt;/span>
&lt;span style="color:#75715e"># * `!:2-3` -&amp;gt; 2. ve 3. parametreyi alır&lt;/span>
&lt;span style="color:#75715e"># * `!:2` -&amp;gt; sadece 2.parametreyi alır&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="misc">Çeşitli&lt;/h2>
&lt;p>&lt;strong>11-&lt;/strong> Eğer Linux terminalinde hızlı bir şekilde takvim görmek istiyorsanız, &lt;code>cal&lt;/code> sizin için biçilmiş bir altın kaftandır.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">&lt;span style="color:#75715e"># varsayılan olarak mevcut ayın takvimini gösterir&lt;/span>
&lt;span style="color:#75715e"># Kullanımı: cal [[month] year]&lt;/span>
&amp;gt;&amp;gt; cal
--- OUTPUT ---
June &lt;span style="color:#ae81ff">2021&lt;/span>
Su Mo Tu We Th Fr Sa
&lt;span style="color:#ae81ff">1&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>
&lt;span style="color:#ae81ff">6&lt;/span> &lt;span style="color:#ae81ff">7&lt;/span> &lt;span style="color:#ae81ff">8&lt;/span> &lt;span style="color:#ae81ff">9&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#ae81ff">11&lt;/span> &lt;span style="color:#ae81ff">12&lt;/span>
&lt;span style="color:#ae81ff">13&lt;/span> &lt;span style="color:#ae81ff">14&lt;/span> &lt;span style="color:#ae81ff">15&lt;/span> &lt;span style="color:#ae81ff">16&lt;/span> &lt;span style="color:#ae81ff">17&lt;/span> &lt;span style="color:#ae81ff">18&lt;/span> &lt;span style="color:#ae81ff">19&lt;/span>
&lt;span style="color:#ae81ff">20&lt;/span> &lt;span style="color:#ae81ff">21&lt;/span> &lt;span style="color:#ae81ff">22&lt;/span> &lt;span style="color:#ae81ff">23&lt;/span> &lt;span style="color:#ae81ff">24&lt;/span> &lt;span style="color:#ae81ff">25&lt;/span> &lt;span style="color:#ae81ff">26&lt;/span>
&lt;span style="color:#ae81ff">27&lt;/span> &lt;span style="color:#ae81ff">28&lt;/span> &lt;span style="color:#ae81ff">29&lt;/span> &lt;span style="color:#ae81ff">30&lt;/span>
&amp;gt;&amp;gt; cal &lt;span style="color:#ae81ff">01&lt;/span> &lt;span style="color:#ae81ff">2010&lt;/span>
--- OUTPUT ---
January &lt;span style="color:#ae81ff">2010&lt;/span>
Su Mo Tu We Th Fr Sa
&lt;span style="color:#ae81ff">1&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>
&lt;span style="color:#ae81ff">3&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span> &lt;span style="color:#ae81ff">6&lt;/span> &lt;span style="color:#ae81ff">7&lt;/span> &lt;span style="color:#ae81ff">8&lt;/span> &lt;span style="color:#ae81ff">9&lt;/span>
&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#ae81ff">11&lt;/span> &lt;span style="color:#ae81ff">12&lt;/span> &lt;span style="color:#ae81ff">13&lt;/span> &lt;span style="color:#ae81ff">14&lt;/span> &lt;span style="color:#ae81ff">15&lt;/span> &lt;span style="color:#ae81ff">16&lt;/span>
&lt;span style="color:#ae81ff">17&lt;/span> &lt;span style="color:#ae81ff">18&lt;/span> &lt;span style="color:#ae81ff">19&lt;/span> &lt;span style="color:#ae81ff">20&lt;/span> &lt;span style="color:#ae81ff">21&lt;/span> &lt;span style="color:#ae81ff">22&lt;/span> &lt;span style="color:#ae81ff">23&lt;/span>
&lt;span style="color:#ae81ff">24&lt;/span> &lt;span style="color:#ae81ff">25&lt;/span> &lt;span style="color:#ae81ff">26&lt;/span> &lt;span style="color:#ae81ff">27&lt;/span> &lt;span style="color:#ae81ff">28&lt;/span> &lt;span style="color:#ae81ff">29&lt;/span> &lt;span style="color:#ae81ff">30&lt;/span>
&lt;span style="color:#ae81ff">31&lt;/span>
&lt;span style="color:#75715e">## daha fazla örnek; cal -4, cal 2018&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>12-&lt;/strong> &lt;code>watch&lt;/code> ile belirtilen komutu otomatik olarak tekrar tekrar çalıştırabilir ve sonuçları standart çıktıda
görüntüleyebilirsiniz, böylece zaman içindeki değişimini de izleyebilirsiniz. &lt;code>watch&lt;/code> Varsayılan olarak, komutu her iki
saniyede bir çalıştırılır, ancak bu &lt;code>-n secs&lt;/code> argümanı ile bu süreyi ayarlayabilirsiniz.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">&lt;span style="color:#75715e"># mesela tüm nodejs process&amp;#39;lerini görüntüleyelim&lt;/span>
&amp;gt;&amp;gt; watch &lt;span style="color:#e6db74">&amp;#34;ps -e | grep node&amp;#34;&lt;/span>
-- OUTPUT --
Every 2s: ps -e | grep node Sat Jun &lt;span style="color:#ae81ff">12&lt;/span> 21:00:00 &lt;span style="color:#ae81ff">2021&lt;/span>
PID TTY TIME CMD
&lt;span style="color:#ae81ff">1167&lt;/span> pts/1 00:00:00 node
&lt;span style="color:#ae81ff">1189&lt;/span> pts/1 00:03:30 node
&lt;span style="color:#ae81ff">1224&lt;/span> pts/2 00:00:00 node
&lt;span style="color:#ae81ff">1235&lt;/span> pts/2 00:00:40 node
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>13-&lt;/strong> Bir çok kişi çok önemsemesede &lt;code>man&lt;/code> komutu da aslında oldukça önemlidir. &lt;code>man&lt;/code> komutu size terminal&amp;rsquo;de
çalıştrabileceğiniz herhangi bir komutun kullanım klavuzunu gösterir. (İsim, Özet, Açıklama, Seçenekler,
Çıkış Durumu, Dönüş Değerleri, Hatalar, Dosyalar, Versiyonlar, Örnekler, Yazarlar ve daha fazlası)&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">&amp;gt;&amp;gt; man xargs
&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="bash-script">Bash Script&lt;/h2>
&lt;p>&lt;strong>14-&lt;/strong> Diyelim ki bir projemizin kurulumu için bash script yazıyoruz ve insanlar yazdığımız bu script&amp;rsquo;i wget ile
internetten indiriyorlar. Fakat burada düşünmemiz gereken bazı durumlar var, örneğin kullanıcı script&amp;rsquo;i internetten
çekerken internet bağlantısı gidebilir veya kötü bir bağlantıya sahip olabilir, bunlara bağlı olarak script&amp;rsquo;in sadece
bir kısmı gelebilir. Daha sonra kullanıcı bunu çalıştırırsa (veya direk inline çalıştıracak şekilde yazdıysa komutu)
sadece var olan kısmı çalışır ve aslında kurulumu yapamamış olur, işleri biraz daha karmaşıklaştırmış olur.&lt;/p>
&lt;p>Bunun önüne geçmek bir &lt;code>main&lt;/code> fonksiyon açıp, normalde fonksiyon dışına yazdığımız kodları bu fonksiyonun içerisine
yazıyoruz. En son satırda da bu fonksiyonu çağırıyoruz. Bu sayede kullanıcı eğer script&amp;rsquo;in tamamını indirmediyse main
fonksiyonu ve ona bağlı olarak çalışan fonksiyonlar da çalışmaz.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">// Other Functions
main&lt;span style="color:#f92672">()&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
// Your Codes
&lt;span style="color:#f92672">}&lt;/span>
main &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$@&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="keyboard-shortcuts">Klavye Kısayolları&lt;/h2>
&lt;p>&lt;strong>15-&lt;/strong> İşinize yarıyacak bazı popüler terminal kısayolları.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Ctrl + R:&lt;/strong> Komut geçmişinizde arama yapar&lt;/li>
&lt;li>&lt;strong>Ctrl + E:&lt;/strong> İmleci en başa götürür&lt;/li>
&lt;li>&lt;strong>Ctrl + A:&lt;/strong> İmleci en sona götürür&lt;/li>
&lt;li>&lt;strong>Ctrl + U:&lt;/strong> İmlecin solundaki kısmı siler&lt;/li>
&lt;li>&lt;strong>Ctrl + K:&lt;/strong> İmlecin sağındaki kısmı siler&lt;/li>
&lt;li>&lt;strong>Ctrl + P:&lt;/strong> Komut geçmişinizde geri gider&lt;/li>
&lt;li>&lt;strong>Ctrl + L:&lt;/strong> Terminal ekranınızı temizler&lt;/li>
&lt;li>&lt;strong>Ctrl + D:&lt;/strong> Eğer aktif bir process&amp;rsquo;in içerisinde iseniz onu kapatır,
değilseniz ve terminal&amp;rsquo;de herhangi bir şey yazılıysa imleçten sonraki karakteri siler, eğer hiçbişe yazılı değilse
kullanıcıdan veya bulunduğun terminal&amp;rsquo;den çıkış yapar&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="son">Son&lt;/h2>
&lt;p>Umarım bu yazıyı okuyarak harcadığınız zamanı, buradan öğrendikleriniz ile telafi edebilirsiniz. Sonraki yazılarda
görüşmek dileğiyle.&lt;/p></content></item><item><title>Cloud Storage'da Static Websitesi Barındırma</title><link>https://anxl.dev/blog/static-website-hosting-on-cloud-storage/</link><pubDate>Wed, 26 May 2021 16:00:00 +0300</pubDate><guid>https://anxl.dev/blog/static-website-hosting-on-cloud-storage/</guid><description>Bu yazıda kısaca static websitelerimizi nasıl Cloud Storage&amp;rsquo;da tek veya multi-region barındırabileceğimize bakacağız.
Static web siteleri, sayfa yayınlandıktan sonra içeriğin nadiren değiştiği veya dinamik olarak oluşturulan içeriğin olmadığı blog, portfolyo gibi siteler için iyi bir seçenektir. Static web siteleri, HTML, CSS ve JavaScript gibi istemci tarafı teknoloji içerebilirler. PHP gibi sunucu taraflı komut dosyaları, yani dinamik içerik içermezler.
Adımlar Bir CNAME kaydı kullanarak alan adımızı Cloud Storage&amp;rsquo;a yönlendirme. Alan adımıza bağlı bir Bucket oluşturma.</description><content>&lt;p>Bu yazıda kısaca static websitelerimizi nasıl Cloud Storage&amp;rsquo;da tek veya multi-region barındırabileceğimize bakacağız.&lt;/p>
&lt;p>Static web siteleri, sayfa yayınlandıktan sonra içeriğin nadiren değiştiği veya dinamik olarak oluşturulan içeriğin
olmadığı blog, portfolyo gibi siteler için iyi bir seçenektir. Static web siteleri, HTML, CSS ve JavaScript gibi istemci
tarafı teknoloji içerebilirler. PHP gibi sunucu taraflı komut dosyaları, yani dinamik içerik içermezler.&lt;/p>
&lt;h2 id="steps">Adımlar&lt;/h2>
&lt;ol>
&lt;li>Bir CNAME kaydı kullanarak alan adımızı Cloud Storage&amp;rsquo;a yönlendirme.&lt;/li>
&lt;li>Alan adımıza bağlı bir Bucket oluşturma.&lt;/li>
&lt;li>Sitemizi, oluşturduğumuz Bucket&amp;rsquo;a yükleme.&lt;/li>
&lt;li>Bucket&amp;rsquo;ımızı internete açık hale getirme.&lt;/li>
&lt;li>Özel index ve 404 sayfaları ayarlama.&lt;/li>
&lt;li>Websitemizi test etme.&lt;/li>
&lt;/ol>
&lt;h2 id="connecting-your-domain-to-cloud-storage">Alan Adınızı Cloud Storage&amp;rsquo;a Bağlayın&lt;/h2>
&lt;p>Alan adınızı (domain) Cloud Storage&amp;rsquo;a bağlamak için alan adı sağlayıcı firmanızın DNS yönetim paneline giriş yapın ve bir
&lt;code>CNAME&lt;/code> kaydı oluşturun. Bizim yapacağımız örnek için bu kayıt şu şekildedir;&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>NAME&lt;/th>
&lt;th>TYPE&lt;/th>
&lt;th>DATA&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>www&lt;/td>
&lt;td>CNAME&lt;/td>
&lt;td>c.storage.googleapis.com&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>Unutmayın:&lt;/strong> Eğer websitenizi bir alt alan adı&amp;rsquo;na (subdomin) kuracaksanız &lt;code>www&lt;/code> yazan yere alt alan adınızı yazın. Ayrıca
isterseniz direk &lt;code>www&lt;/code> olmadan da ana alan adınıza yönlendirebilirsiniz. Eğer CloudFlare gibi sağlayıcılar kullanıyorsanız
&lt;code>www&lt;/code> to &lt;code>non-www&lt;/code> gibi hileler yapabilirsiniz. Burası size kalmış.&lt;/p>
&lt;p>&lt;strong>NOT:&lt;/strong> Burdan sonra ki adımları ben Google Cloud&amp;rsquo;un CLI&amp;rsquo;ndan yapıcam. Siz isterseniz tüm adımları komutlarda ki
keyword&amp;rsquo;leri Google Cloud Console&amp;rsquo;un UI&amp;rsquo;ndan bularak da yapabilirsiniz.&lt;/p>
&lt;h2 id="creating-a-bucket">Bucket Oluşturun&lt;/h2>
&lt;p>Adı, alanınız için oluşturduğunuz &lt;code>CNAME&lt;/code> kaydı ile eşleşen bir Bucket oluşturun.&lt;/p>
&lt;p>Örneğin, &lt;em>example.com&lt;/em>&amp;lsquo;un &lt;em>www&lt;/em> alt alanından &lt;code>c.storage.googleapis.com&lt;/code>&amp;lsquo;a işaret eden bir &lt;code>CNAME&lt;/code> kaydı
eklediyseniz, &lt;strong>&amp;ldquo;&lt;a href="http://www.example.com">www.example.com&lt;/a>&amp;rdquo;&lt;/strong> adında bir Bucket oluşturun.&lt;/p>
&lt;p>Örnek bir Bucket oluşturma;&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-shell" data-lang="shell">gsutil mb gs://www.example.com
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Ek olarak &lt;code>-l&lt;/code> parametresi ile Bucket&amp;rsquo;ınızın bölgesini (asya, avrupa, multi-region vb.), &lt;code>-c&lt;/code> parametresi ile sınıfını
(nearline, cold, standart vb.), &lt;code>--retention&lt;/code> parametresi ile de içindeki dosyaların ne kadar süre Bucket&amp;rsquo;da saklanacağını belirtebilirsiniz.&lt;/p>
&lt;p>&lt;strong>Dikkat:&lt;/strong> Bucket&amp;rsquo;a alan adınızın ismini verebilmeniz için, &lt;a href="https://search.google.com/search-console">Google Search Console&lt;/a>
üzerinde alan adının size ait olduğunun doğrulanmış olması gerekir. Aksi takdirde herhangi bir domain için Bucket
oluşturamazsınız. Bu konuda daha detaylı bilgi için burayı inceleyebilirsiniz: &lt;a href="https://cloud.google.com/storage/docs/domain-name-verification">https://cloud.google.com/storage/docs/domain-name-verification&lt;/a>&lt;/p>
&lt;h2 id="uploading-your-site">Sitenizi Yükleyin&lt;/h2>
&lt;p>Evet Bucket oluşturduğumuza göre sıra websitemizde sunmak istediğimiz içeriğine yani dosyalarımıza geldi.&lt;/p>
&lt;p>Bilgisayarınızdaki bir dosyayı Bucket&amp;rsquo;a kopyalamak için &lt;code>cp&lt;/code> komutunu kullanabilirsiniz;&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-shell" data-lang="shell">gsutil cp Desktop/index.html gs://www.example.com
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Eğer çok fazla sayıda dosya kopyalamak istiyorsanız, &lt;code>-R&lt;/code> parametresi eşliğinde &lt;code>rsync&lt;/code> komutunu kullanın. Bu komut klasör
ve dosyalarınızı recursive (özyinelemeli) şekilde Bucket&amp;rsquo;ınıza kopyalar. &lt;code>local-dir&lt;/code> adlı bir klasör için örnek;&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-shell" data-lang="shell">gsutil rsync -R local-dir gs://www.example.com
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="sharing-your-files">Dosyalarınızı Herkese Açık Hale Getirin&lt;/h2>
&lt;p>Cloud Storage&amp;rsquo;da oluşturduğunuz Bucket&amp;rsquo;lar varsayılan olarak internete kapalıdır. Biz websitemizi insanlara açmak istediğimiz
için internete açıcağız. Dosyalarınızın hassas veya özel bilgiler içermediğinden eminseniz, aşağıdaki komutu kullanarak sitenizi
herkese açık hale getirebilirsiniz.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-shell" data-lang="shell">gsutil iam ch allUsers:legacyObjectReader gs://www.example.com
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Eğer Bucket&amp;rsquo;daki dosyaların listesini insanların görebilmesini istiyorsanız &lt;code>allUsers:objectViewer&lt;/code> yetkisini kullanabilirsiniz.&lt;/p>
&lt;h2 id="assigning-specialty-pages">Özel Index ve 404 Sayfası Atayın&lt;/h2>
&lt;p>Bir diğer önemli nokta ise index ve 404 sayfamız. Cloud Storage kullanıcın istediği bir dosyayı bulamadığı zaman otomatik
olarak &lt;code>403&lt;/code> hata kodu döndürür. Buda sizin kullanıcıya bir 404 sayfası göstermeniz gerektiği anlamına gelir, aksi takdirde
kullanıcıya bir içerik sağlanmaz. Bunun için &lt;code>web&lt;/code> komutunu kullanabilirsiniz;&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-shell" data-lang="shell">gsutil web set -m index.html -e 404.html gs://www.example.com
&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;code>-m&lt;/code> parametresi sizin ana sayfanızı temsil eder.&lt;/li>
&lt;li>&lt;code>-e&lt;/code> parametresi 404 sayfasını temsil eder.&lt;/li>
&lt;/ul>
&lt;h2 id="testing-the-website">Websitenizi Test Edin&lt;/h2>
&lt;p>Örneğin &lt;code>www.example.com&lt;/code> adını koyduğunuz Bucket&amp;rsquo;ınızın içerisinde &lt;code>test.html&lt;/code> adında bir dosya varsa arama motorunuzdan
&lt;code>www.example.com/test.html&lt;/code> adresine gidin. Eğer olması gereken içerik karşınıza çıktıysa tebrikler, artık static websiteniz
Cloud Storage&amp;rsquo;da barınıyor, fakat karşınıza bir içerik çıkmadıysa bir şeyleri yanlış yapmışsınız demektir. Yaptıklarınızı
gözden geçirin ve tekrar deneyin.&lt;/p>
&lt;h2 id="high-level-architecture">Yüksek Seviye Tasarım&lt;/h2>
&lt;p>Websitemizin altyapısı genel olarak buna benzemiş oluyor.&lt;/p>
&lt;img src="https://anxl.dev/images/static-website-hosting-on-cloud-storage/cloud-storage-diagram.svg" class="left" />
&lt;h2 id="cleaning-up">Ekstra: Yarattığınızı Bucket&amp;rsquo;ı Silmek&lt;/h2>
&lt;p>Eğer yarattığınız Bucket&amp;rsquo;ı ve silmek istiyorsanız &lt;code>rm&lt;/code> komutunu kullanabilirsiniz. İşte bir örnek;&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-shell" data-lang="shell">gsutil rm -r gs://www.example.com
&lt;/code>&lt;/pre>&lt;/div>&lt;p>(&lt;code>-r&lt;/code>) parametresi Bucket içerisinde ki içeriğinde silinmesini sağlar.&lt;/p>
&lt;p>Okuduğunuz için teşekkürler, umarım konuyu anlayabilmiş ve yazıyı beğenmişsinizdir. Bir sonra ki yazılarda görüşmek
dileğiyle.&lt;/p></content></item><item><title>OpenTelemetry ve Cloud Trace Kullanarak Servislerizi Dağıtık Olarak İzleyin</title><link>https://anxl.dev/blog/open-telemetry-and-cloud-trace/</link><pubDate>Tue, 25 May 2021 16:00:00 +0300</pubDate><guid>https://anxl.dev/blog/open-telemetry-and-cloud-trace/</guid><description>Dağıtılmış izleme, çok katmanlı bir mikro servis mimarisine ilişkin öngörü ve gözlemlenebilirlik elde etmek için önemlidir. Servis A&amp;rsquo;dan servis B&amp;rsquo;ye servis çağrılarına, servis çağrılarına zincirleme yaptığınızda, çağrıların başarılı olduğunu ve ayrıca her adımdaki gecikmeyi anlamak önemlidir.
İşte tam da bu noktada karşımıza Cloud Trace çıkıyor. Cloud Trace servislerimizi izlemek için dağıtık bir Cloud çözümüdür. Bu yazıda Cloud Trace&amp;rsquo;i anlamak için basit bir Go uygulaması yazıcaz ve OpenTelemetry Go SDK&amp;rsquo;i kullarak uygulamamızı izleyeceğiz.</description><content>&lt;p>Dağıtılmış izleme, çok katmanlı bir mikro servis mimarisine ilişkin öngörü ve gözlemlenebilirlik elde etmek için
önemlidir. Servis A&amp;rsquo;dan servis B&amp;rsquo;ye servis çağrılarına, servis çağrılarına zincirleme yaptığınızda, çağrıların başarılı
olduğunu ve ayrıca her adımdaki gecikmeyi anlamak önemlidir.&lt;/p>
&lt;p>İşte tam da bu noktada karşımıza Cloud Trace çıkıyor. Cloud Trace servislerimizi izlemek için dağıtık bir Cloud çözümüdür.
Bu yazıda Cloud Trace&amp;rsquo;i anlamak için basit bir Go uygulaması yazıcaz ve OpenTelemetry Go SDK&amp;rsquo;i kullarak uygulamamızı
izleyeceğiz.&lt;/p>
&lt;hr>
&lt;h2 id="what-is-open-telemetry">Kısaca OpenTelemetry Nedir?&lt;/h2>
&lt;p>OpenTelemetry 2019 yılında OpenCensus ve OpenTracing projelerinin birleşmesiyle oluşmuş, uygulamanızı
dağıtık biçimde izleme ve ölçüm yapmak için tek bir API seti sağlayan, kitaplık ve toplayıcı hizmetidir.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Dikkat:&lt;/strong> OpenTelemetry tracing özelliği 2021 Şubat ayı itibariyle 1.0 sürümüne ulaşmıştır. Go SDK&amp;rsquo;i ise henüz &lt;strong>Pre-GA&lt;/strong>
aşamasında olduğundan, bu %100 kararlı genel kullanılabilir hale gelene kadar bazı şeylerin değişebileceği anlamına gelir.&lt;/p>
&lt;/blockquote>
&lt;hr>
&lt;h2 id="overview">Genel Bakış&lt;/h2>
&lt;p>Uygulamaya geçmeden önce kısa bir ön bilgi ile bazı OpenTelemetry terimlerini tanıyalım.&lt;/p>
&lt;img src="https://anxl.dev/images/open-telemetry-and-cloud-trace/diagram.png" alt="open telemetry diagram" class="center" style="border-radius: 8px;" />
&lt;h4 id="-span">&amp;gt; Span&lt;/h4>
&lt;p>&lt;strong>&amp;ldquo;Span&amp;rdquo;&lt;/strong>, dağıtık bir sistemde yapılan bağımsız iş birimini temsil eden, dağıtılmış bir sistemi izlemenin birincil
yapı taşıdır.&lt;/p>
&lt;p>Dağıtılmış sistemin her bileşeni, iş akışının bir parçasını temsil eden, adlandırılmış ve zamanlanmış bir işlem olan bir
Span&amp;rsquo;a katkıda bulunur.&lt;/p>
&lt;p>Span&amp;rsquo;ler, diğer Span&amp;rsquo;ler için &amp;ldquo;Referanslar&amp;rdquo; içerebilirler, bu da birden fazla Span&amp;rsquo;in tek bir yerde
birleştirilmesine olanak sağlar ve bir talebin ömrünün, dağıtık bir sistemde hareket ederken görselleştirilmesi sağlanır.&lt;/p>
&lt;p>Her &lt;strong>Span&lt;/strong>, OpenTelemetry spesifikasyonuna göre aşağıdaki maddeleri içerisinde barındırır:&lt;/p>
&lt;ul>
&lt;li>Span adı&lt;/li>
&lt;li>Durum&lt;/li>
&lt;li>Bir başlangıç ve bitiş zaman damgası&lt;/li>
&lt;li>Span&amp;rsquo;ı benzersiz şekilde tanımlayan değişmez bir SpanContext&lt;/li>
&lt;li>Zaman damgalı olarak &lt;strong>Event&lt;/strong>&amp;lsquo;lerin listesi&lt;/li>
&lt;li>Span, SpanContext veya null biçimindeki bir üst yayılma alanı&lt;/li>
&lt;li>Span&amp;rsquo;in Öznitelikleri&lt;/li>
&lt;li>Span&amp;rsquo;in Türü&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>&lt;strong>Dikkat:&lt;/strong> Span&amp;rsquo;ler isimlendirilirken insanların anlıyabileceği şekilde isimlendirmek önemlidir.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Span Adı&lt;/th>
&lt;th>Kılavuz&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>get&lt;/code>&lt;/td>
&lt;td>Çok genel&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>get_account/42&lt;/code>&lt;/td>
&lt;td>Çok spesifik&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>get_account&lt;/code>&lt;/td>
&lt;td>Gayet iyi, ayrıca &lt;code>account_id=42&lt;/code> güzel bir Span özniteliği olabilir&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>get_account/{account_id}&lt;/code>&lt;/td>
&lt;td>Daha da iyi (HTTP endpoint&amp;rsquo;ini gösteriyor)&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/blockquote>
&lt;h4 id="-spancontext">&amp;gt; SpanContext&lt;/h4>
&lt;p>SpanContext, bir Span&amp;rsquo;in içeriğini tutan değiştirilemez yapıdır. OpenTelemetry spesifikasyonuna göre içerisinde
şunları barındırır:&lt;/p>
&lt;ul>
&lt;li>TraceId &lt;em>(16 byte)&lt;/em>&lt;/li>
&lt;li>SpanId &lt;em>(8 byte)&lt;/em>&lt;/li>
&lt;li>TraceFlags&lt;/li>
&lt;li>TrackState&lt;/li>
&lt;/ul>
&lt;h4 id="-tracer--tracerprovider">&amp;gt; Tracer &amp;amp; TracerProvider&lt;/h4>
&lt;p>Tracer, Span oluşturmaktan sorumlu birimdir. TracerProvider ise oluşturduğumuz Tracer&amp;rsquo;lara ulaşmamızı sağlar.&lt;/p>
&lt;hr>
&lt;h2 id="learn-it-practically">Uygulamalı Olarak Öğrenelim&lt;/h2>
&lt;p>Bunun için basit bir kurgu oluşturalım. Örneğin bir HTTP sunucumuz olsun ve &lt;code>/run&lt;/code> endpoint&amp;rsquo;ine istek geldiği zaman
&lt;code>golang/go&lt;/code> projesinin GitHub&amp;rsquo;daki bazı istatistiklerini kullanıcının önündeki sayfaya yazdırsın ve bunu yaparkende
hangi işlemin ne kadar sürdüğünü göstersin.&lt;/p>
&lt;h4 id="preparation">Hazırlık&lt;/h4>
&lt;p>Başlamadan önce OpenTelemetry&amp;rsquo;nin ve Google Cloud&amp;rsquo;un Go paketlerini kurmamız gerekiyor.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">go get -u go.opentelemetry.io/otel
go get -u github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="main">Main&lt;/h4>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-go" data-lang="go">&lt;span style="color:#75715e">// GitHub API dökümanlarına göre oluşturduğumuz Go veri yapımız
&lt;/span>&lt;span style="color:#75715e">// ref: https://docs.github.com/en/rest/reference/repos#get-a-repository
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">Repository&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;span style="color:#a6e22e">Id&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#e6db74">`json:&amp;#34;id&amp;#34;`&lt;/span>
&lt;span style="color:#a6e22e">StargazersCount&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#e6db74">`json:&amp;#34;stargazers_count&amp;#34;`&lt;/span>
&lt;span style="color:#a6e22e">Forks&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#e6db74">`json:&amp;#34;forks&amp;#34;`&lt;/span>
&lt;span style="color:#a6e22e">Name&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span> &lt;span style="color:#e6db74">`json:&amp;#34;name&amp;#34;`&lt;/span>
&lt;span style="color:#a6e22e">FullName&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span> &lt;span style="color:#e6db74">`json:&amp;#34;full_name&amp;#34;`&lt;/span>
}
&lt;span style="color:#66d9ef">var&lt;/span> (
&lt;span style="color:#a6e22e">httpClient&lt;/span> = &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">Client&lt;/span>{&lt;span style="color:#a6e22e">Timeout&lt;/span>: &lt;span style="color:#ae81ff">5&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">time&lt;/span>.&lt;span style="color:#a6e22e">Second&lt;/span>}
&lt;span style="color:#a6e22e">tracer&lt;/span> &lt;span style="color:#a6e22e">trace&lt;/span>.&lt;span style="color:#a6e22e">Tracer&lt;/span>
)
&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;span style="color:#a6e22e">initTracer&lt;/span>() &lt;span style="color:#75715e">// Tracer&amp;#39;ımızı başlatıyoruz
&lt;/span>&lt;span style="color:#75715e">&lt;/span>
&lt;span style="color:#a6e22e">serveHTTP&lt;/span>() &lt;span style="color:#75715e">// HTTP sunucumuzu başlatıyoruz
&lt;/span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Önce GitHub API&amp;rsquo;ndan gelecek yanıt için bir veri yapısı oluşturduk, daha sonra HTTP Client&amp;rsquo;ımızı ve ileride initialize
edeceğimiz Tracer&amp;rsquo;ımızı belirledik. En sonda ise servisimiz çalışmaya başladığında otomatik olarak çalıştırılacak olan
&lt;code>main&lt;/code> fonksiyonunu yazıp, içinde &lt;code>initTracer&lt;/code> ve &lt;code>serveHTTP&lt;/code> adında iki farklı fonksiyon çağırdık. Bu fonksiyonları
sonraki adımlarda tanımlayacağız.&lt;/p>
&lt;h4 id="http-server">HTTP Server&lt;/h4>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-go" data-lang="go">&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">serveHTTP&lt;/span>() {
&lt;span style="color:#a6e22e">port&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Getenv&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;PORT&amp;#34;&lt;/span>) &lt;span style="color:#75715e">// ortam değişkenlerinden `PORT` değerini al
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">port&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span> {
&lt;span style="color:#a6e22e">port&lt;/span> = &lt;span style="color:#e6db74">&amp;#34;8080&amp;#34;&lt;/span> &lt;span style="color:#75715e">// eğer yoksa varsayılan olarak olarak `8080` portunu kullan
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;defaulting to port %s&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">port&lt;/span>)
}
&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">HandleFunc&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;/run&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">handler&lt;/span>) &lt;span style="color:#75715e">// run endpoint&amp;#39;i için bir handler ayarla
&lt;/span>&lt;span style="color:#75715e">&lt;/span>
&lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;server starting at: %s&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">port&lt;/span>)
&lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatal&lt;/span>(&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">ListenAndServe&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;:&amp;#34;&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#a6e22e">port&lt;/span>, &lt;span style="color:#66d9ef">nil&lt;/span>)) &lt;span style="color:#75715e">// sunucuya başlat
&lt;/span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Go içerisinde built-in bir şekilde gelen &lt;code>net/http&lt;/code> paketi ile oldukça kolay bir şekilde HTTP server yaratabilirsiniz. Üstteki
kod parçamızda da &lt;code>serverHTTP&lt;/code> metodunda bir HTTP server yarattık ve &lt;code>/run&lt;/code> endpoint&amp;rsquo;i için bir handler fonksiyonu
belirledik. Bu fonksiyonu da ileriki adımlarda tanımlayacağız.&lt;/p>
&lt;h4 id="initialize-tracer">Initialize Tracer&lt;/h4>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-go" data-lang="go">&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">initTracer&lt;/span>() {
&lt;span style="color:#75715e">// Cloud Trace Exporter&amp;#39;ımız
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">exporter&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">texporter&lt;/span>.&lt;span style="color:#a6e22e">NewExporter&lt;/span>(&lt;span style="color:#a6e22e">texporter&lt;/span>.&lt;span style="color:#a6e22e">WithTraceClientOptions&lt;/span>([]&lt;span style="color:#a6e22e">option&lt;/span>.&lt;span style="color:#a6e22e">ClientOption&lt;/span>{
&lt;span style="color:#a6e22e">option&lt;/span>.&lt;span style="color:#a6e22e">WithTelemetryDisabled&lt;/span>(), &lt;span style="color:#75715e">// exporter&amp;#39;ın kendinide izlemesini kapattık
&lt;/span>&lt;span style="color:#75715e">&lt;/span> }))
&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatalf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;texporter.NewExporter: %v&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>)
}
&lt;span style="color:#75715e">// Yeni bir TracerProvider oluşturuyoruz
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">tp&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">sdktrace&lt;/span>.&lt;span style="color:#a6e22e">NewTracerProvider&lt;/span>(&lt;span style="color:#a6e22e">sdktrace&lt;/span>.&lt;span style="color:#a6e22e">WithBatcher&lt;/span>(&lt;span style="color:#a6e22e">exporter&lt;/span>,
&lt;span style="color:#75715e">// yığını her saniyede bir gönder
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">sdktrace&lt;/span>.&lt;span style="color:#a6e22e">WithBatchTimeout&lt;/span>(&lt;span style="color:#a6e22e">time&lt;/span>.&lt;span style="color:#a6e22e">Second&lt;/span>),
&lt;span style="color:#75715e">// maksimum yığın büyüklüğü
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">sdktrace&lt;/span>.&lt;span style="color:#a6e22e">WithMaxExportBatchSize&lt;/span>(&lt;span style="color:#ae81ff">16&lt;/span>)),
&lt;span style="color:#75715e">// bu sadece örnek öznitelikler eklemesi için varolan bir ayar
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// bunu production ortamında yazmanıza gerek yok
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">sdktrace&lt;/span>.&lt;span style="color:#a6e22e">WithSampler&lt;/span>(&lt;span style="color:#a6e22e">sdktrace&lt;/span>.&lt;span style="color:#a6e22e">AlwaysSample&lt;/span>()),
&lt;span style="color:#75715e">// tüm Span&amp;#39;lere eklenicek attribute&amp;#39;ler
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">sdktrace&lt;/span>.&lt;span style="color:#a6e22e">WithResource&lt;/span>(&lt;span style="color:#a6e22e">resource&lt;/span>.&lt;span style="color:#a6e22e">NewWithAttributes&lt;/span>(
&lt;span style="color:#a6e22e">attribute&lt;/span>.&lt;span style="color:#a6e22e">String&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;service.name&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;sample-service&amp;#34;&lt;/span>),
&lt;span style="color:#a6e22e">attribute&lt;/span>.&lt;span style="color:#a6e22e">String&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;service.version&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;1.0.0&amp;#34;&lt;/span>),
&lt;span style="color:#a6e22e">attribute&lt;/span>.&lt;span style="color:#a6e22e">String&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;instance.id&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;foo12345&amp;#34;&lt;/span>),
)),
)
&lt;span style="color:#75715e">// Global olarak TracerProvider&amp;#39;ımızı belirtiyoruz
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">otel&lt;/span>.&lt;span style="color:#a6e22e">SetTracerProvider&lt;/span>(&lt;span style="color:#a6e22e">tp&lt;/span>)
&lt;span style="color:#75715e">// Global olarak belirttiğimiz TracerProvider&amp;#39;ımızından Tracer&amp;#39;ımızı alıyoruz
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">tracer&lt;/span> = &lt;span style="color:#a6e22e">otel&lt;/span>.&lt;span style="color:#a6e22e">GetTracerProvider&lt;/span>().&lt;span style="color:#a6e22e">Tracer&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;company.com/trace&amp;#34;&lt;/span>)
&lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#66d9ef">func&lt;/span>() {
&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">tp&lt;/span>.&lt;span style="color:#a6e22e">ForceFlush&lt;/span>(&lt;span style="color:#a6e22e">context&lt;/span>.&lt;span style="color:#a6e22e">Background&lt;/span>()); &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;failed to flush tracer&amp;#34;&lt;/span>)
}
}()
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Burada ise Span&amp;rsquo;lerimizi &lt;strong>Cloud Trace&lt;/strong>&amp;lsquo;e göndermek için bir Exporter oluşturduk ve bazı ayarlar ile yeni bir TracerProvider
yaratıp, bunu global olarak belirttik.&lt;/p>
&lt;p>Yukarıdaki örnekte Google Cloud ile authenticate yaparken ben Application Default credentials&amp;rsquo;ları kullandım.
Bu kodları local&amp;rsquo;de çalıştırmaya çalıştırdığınızda &lt;code>Permission Denied&lt;/code> hatası almanız olasıdır. Google Cloud
ortamlarında bu credentials&amp;rsquo;lar zaten hali hazırda bulunur ve sizin ek olarak bir şey yapmanıza gerek kalmaz. Fakat local
development için bunu sizin sağlamanız gerekir. Bu ayrı bir makale konusu olduğu için buna şu an burada değinmiyorum.&lt;/p>
&lt;p>Fakat bunu nasıl yapıcağınızı öğrenmek için bir kaç yardımcı kaynağı buraya bırakıyorum:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://cloud.google.com/docs/authentication/production">https://cloud.google.com/docs/authentication/production&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://cloud.google.com/sdk/gcloud/reference/auth/application-default">https://cloud.google.com/sdk/gcloud/reference/auth/application-default&lt;/a>&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>&lt;strong>Önemli:&lt;/strong> Genelde örneklerde TelemetryProvider şu şekilde tanımlanır:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-go" data-lang="go">&lt;span style="color:#a6e22e">tp&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">sdktrace&lt;/span>.&lt;span style="color:#a6e22e">NewTracerProvider&lt;/span>(&lt;span style="color:#a6e22e">sdktrace&lt;/span>.&lt;span style="color:#a6e22e">WithSyncer&lt;/span>(&lt;span style="color:#a6e22e">exporter&lt;/span>))
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Fakat bu şekilde tanımlarsanız, her Span bittiği zaman veriyi Google Cloud&amp;rsquo;a göndermeye çalışır. Bu da sizin &lt;strong>100ms&lt;/strong> sürecek
işleminizi kat ve kat uzatabilir.&lt;/p>
&lt;p>Örneklerde Span&amp;rsquo;in olası bir durumda kaybolmaması için böyle yapılmasını öneriyor olabilir
fakat bu yanlış bir yaklaşım diyebiliriz. Bu durum kullanıcıyı etkiler, ekranda daha uzun süre beklemesine yol açar.&lt;/p>
&lt;p>Bunun yerine yukarıdaki örnekteki gibi arka planda, belli zaman aralıkları ile &lt;em>(bizim yaptığımız örnek için bu süre 1 saniye)&lt;/em>
toplu bir şekilde Span&amp;rsquo;leri göndermek bizim için daha verimli olur.&lt;/p>
&lt;p>Bu sayede işlem olması gerektiği sürede tamamlanır. Olası
bir durumda ise en fazla 1 saniye aralıktaki Span&amp;rsquo;leri kaybedersiniz, ki bu kabul edilebilir bir değer.&lt;/p>
&lt;/blockquote>
&lt;h4 id="handler-and-tracing">Handler &amp;amp; Tracing&lt;/h4>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-go" data-lang="go">&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">handler&lt;/span>(&lt;span style="color:#a6e22e">w&lt;/span> &lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">ResponseWriter&lt;/span>, &lt;span style="color:#a6e22e">r&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">Request&lt;/span>) {
&lt;span style="color:#75715e">// `/run` adında yeni bir Span oluşturuyoruz ve start timestamp&amp;#39;ini başlatıyoruz
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// subCtx = sub context
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">subCtx&lt;/span>, &lt;span style="color:#a6e22e">span&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">tracer&lt;/span>.&lt;span style="color:#a6e22e">Start&lt;/span>(&lt;span style="color:#a6e22e">r&lt;/span>.&lt;span style="color:#a6e22e">Context&lt;/span>(), &lt;span style="color:#e6db74">&amp;#34;/run&amp;#34;&lt;/span>)
&lt;span style="color:#75715e">// event ekliyoruz ve ne olduğunu yazıyoruz
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// burası için event &amp;#39;handling request&amp;#39;
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">span&lt;/span>.&lt;span style="color:#a6e22e">AddEvent&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;handling request&amp;#34;&lt;/span>)
&lt;span style="color:#75715e">// en başta tanımladığımız Repository modelinden yeni bir tane oluşturuyoruz
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">repo&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> new(&lt;span style="color:#a6e22e">Repository&lt;/span>)
&lt;span style="color:#75715e">// sub context kullanarak GitHub API&amp;#39;ından `golang/go` projesinin
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// istatistiklerini çekiyoruz.
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">fetchJSON&lt;/span>(&lt;span style="color:#a6e22e">subCtx&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;https://api.github.com/repos/golang/go&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">repo&lt;/span>)
&lt;span style="color:#75715e">// burada sub context ile yeni bir Span oluşturuyoruz ve adını &amp;#39;write&amp;#39; koyuyoruz
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// yani bu durumda ilk oluşturduğumuz Span bizim root Span&amp;#39;imiz olurken
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// burada oluşturduğumuz Span, Child oluyor
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">wSpan&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">tracer&lt;/span>.&lt;span style="color:#a6e22e">Start&lt;/span>(&lt;span style="color:#a6e22e">subCtx&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;write&amp;#34;&lt;/span>)
&lt;span style="color:#75715e">// en son gelin oluşturduğumuz Span&amp;#39;i bitirmesini yani end timestamp&amp;#39;ini yazmasını istiyoruz
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">wSpan&lt;/span>.&lt;span style="color:#a6e22e">End&lt;/span>()
&lt;span style="color:#75715e">// eğer hata varsa diye hatayı kontrol ediyoruz
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;span style="color:#a6e22e">w&lt;/span>.&lt;span style="color:#a6e22e">WriteHeader&lt;/span>(&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">StatusInternalServerError&lt;/span>)
&lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">_&lt;/span> = &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprintf&lt;/span>(&lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">MultiWriter&lt;/span>(&lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Stderr&lt;/span>, &lt;span style="color:#a6e22e">w&lt;/span>), &lt;span style="color:#e6db74">&amp;#34;error: %v\n&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>)
&lt;span style="color:#66d9ef">return&lt;/span>
}
&lt;span style="color:#75715e">// burada hata olmadığını doğruladığımız için root Span&amp;#39;imize dönen veriye göre bazı
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// attribute&amp;#39;ler yani öznitelikler atıyoruz
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">span&lt;/span>.&lt;span style="color:#a6e22e">SetAttributes&lt;/span>(
&lt;span style="color:#a6e22e">attribute&lt;/span>.&lt;span style="color:#a6e22e">String&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;golang.go.repo.name&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">repo&lt;/span>.&lt;span style="color:#a6e22e">FullName&lt;/span>),
&lt;span style="color:#a6e22e">attribute&lt;/span>.&lt;span style="color:#a6e22e">Int&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;golang.go.repo.id&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">repo&lt;/span>.&lt;span style="color:#a6e22e">Id&lt;/span>),
&lt;span style="color:#a6e22e">attribute&lt;/span>.&lt;span style="color:#a6e22e">Int&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;golang.go.repo.stars&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">repo&lt;/span>.&lt;span style="color:#a6e22e">StargazersCount&lt;/span>),
)
&lt;span style="color:#75715e">// sonucu ekrana yazdırıyoruz
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">_&lt;/span> = &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprintf&lt;/span>(&lt;span style="color:#a6e22e">w&lt;/span>,
&lt;span style="color:#e6db74">&amp;#34;===== %s =====\nRepository: %s (ID: %d)\nStar Count: %d\nFork Count: %d\nURL: https://github.com/%s&amp;#34;&lt;/span>,
&lt;span style="color:#a6e22e">repo&lt;/span>.&lt;span style="color:#a6e22e">FullName&lt;/span>, &lt;span style="color:#a6e22e">repo&lt;/span>.&lt;span style="color:#a6e22e">Name&lt;/span>, &lt;span style="color:#a6e22e">repo&lt;/span>.&lt;span style="color:#a6e22e">Id&lt;/span>, &lt;span style="color:#a6e22e">repo&lt;/span>.&lt;span style="color:#a6e22e">StargazersCount&lt;/span>, &lt;span style="color:#a6e22e">repo&lt;/span>.&lt;span style="color:#a6e22e">Forks&lt;/span>, &lt;span style="color:#a6e22e">repo&lt;/span>.&lt;span style="color:#a6e22e">FullName&lt;/span>,
)
&lt;span style="color:#75715e">// root Span&amp;#39;imizi sonlandırıyoruz
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">span&lt;/span>.&lt;span style="color:#a6e22e">End&lt;/span>()
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Burada kısaca GitHub API&amp;rsquo;ndan &lt;code>go/golang&lt;/code> projesinin bilgisini çekip ekrana yazdırdık ve bunu yaparken gelen yanıtın
ekrana ne kadar sürede yazdırıldığını ve tüm işlemin ne kadar sürdüğünü görmek için 1 root 1 child olmak üzere 2 adet &lt;strong>Span&lt;/strong> yaratıp
bir kaç &lt;code>attribute&lt;/code> ve &lt;code>event&lt;/code> ekledik.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-go" data-lang="go">&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">fetchJSON&lt;/span>(&lt;span style="color:#a6e22e">ctx&lt;/span> &lt;span style="color:#a6e22e">context&lt;/span>.&lt;span style="color:#a6e22e">Context&lt;/span>, &lt;span style="color:#a6e22e">url&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#a6e22e">target&lt;/span> &lt;span style="color:#66d9ef">interface&lt;/span>{}) &lt;span style="color:#66d9ef">error&lt;/span> {
&lt;span style="color:#75715e">// yine bir Span yarattık, bu Span&amp;#39;in amacı adındanda anlaşılacağı
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// üzere GitHub API&amp;#39;ndan verinin gelme süresini bize göstericek
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// unutmayın: gelen context, sub context olduğu için bu Span&amp;#39;de child oluyor
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">subCtx&lt;/span>, &lt;span style="color:#a6e22e">span&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">tracer&lt;/span>.&lt;span style="color:#a6e22e">Start&lt;/span>(&lt;span style="color:#a6e22e">ctx&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;fetch json&amp;#34;&lt;/span>)
&lt;span style="color:#75715e">// bu sefer yolladığımız request&amp;#39;de olağandışı bir durum olursa oluşturduğumuz
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// Span&amp;#39;in sonsuza kadar devam etmemesi için Span Context&amp;#39;ine bir timeout koyduk
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">cancel&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">context&lt;/span>.&lt;span style="color:#a6e22e">WithTimeout&lt;/span>(&lt;span style="color:#a6e22e">subCtx&lt;/span>, &lt;span style="color:#a6e22e">time&lt;/span>.&lt;span style="color:#a6e22e">Second&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span>)
&lt;span style="color:#75715e">// eğer her şey yolunda giderse en son gelip bu timeout&amp;#39;u iptal etmesini söyledik
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">cancel&lt;/span>()
&lt;span style="color:#75715e">// Tam bu anda GitHub API&amp;#39;ına request gönderildiğini bildirmek için bir event ekledik
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">span&lt;/span>.&lt;span style="color:#a6e22e">AddEvent&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;fetching repo info from github&amp;#34;&lt;/span>)
&lt;span style="color:#a6e22e">r&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">httpClient&lt;/span>.&lt;span style="color:#a6e22e">Get&lt;/span>(&lt;span style="color:#a6e22e">url&lt;/span>)
&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span>
}
&lt;span style="color:#75715e">// requst&amp;#39;den dönen cevabın durum kodunu &amp;#39;attribute&amp;#39; olarak ekledik
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">span&lt;/span>.&lt;span style="color:#a6e22e">SetAttributes&lt;/span>(&lt;span style="color:#a6e22e">attribute&lt;/span>.&lt;span style="color:#a6e22e">KeyValue&lt;/span>{
&lt;span style="color:#a6e22e">Key&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;github.resp.status.code&amp;#34;&lt;/span>,
&lt;span style="color:#a6e22e">Value&lt;/span>: &lt;span style="color:#a6e22e">attribute&lt;/span>.&lt;span style="color:#a6e22e">IntValue&lt;/span>(&lt;span style="color:#a6e22e">r&lt;/span>.&lt;span style="color:#a6e22e">StatusCode&lt;/span>),
})
&lt;span style="color:#75715e">// en başta oluşturduğumuz Span&amp;#39;i sonlandırdık
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">span&lt;/span>.&lt;span style="color:#a6e22e">End&lt;/span>()
&lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">Body&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">ReadCloser&lt;/span>) {
&lt;span style="color:#a6e22e">_&lt;/span> = &lt;span style="color:#a6e22e">Body&lt;/span>.&lt;span style="color:#a6e22e">Close&lt;/span>()
}(&lt;span style="color:#a6e22e">r&lt;/span>.&lt;span style="color:#a6e22e">Body&lt;/span>)
&lt;span style="color:#75715e">// JSON parse süremizi hesaplamak için bir child Span daha oluşturduk
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">span&lt;/span> = &lt;span style="color:#a6e22e">tracer&lt;/span>.&lt;span style="color:#a6e22e">Start&lt;/span>(&lt;span style="color:#a6e22e">ctx&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;parse json&amp;#34;&lt;/span>)
&lt;span style="color:#75715e">// burada da en son gelip bu Span&amp;#39;i bitirmesini söyledik
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">span&lt;/span>.&lt;span style="color:#a6e22e">End&lt;/span>()
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">json&lt;/span>.&lt;span style="color:#a6e22e">NewDecoder&lt;/span>(&lt;span style="color:#a6e22e">r&lt;/span>.&lt;span style="color:#a6e22e">Body&lt;/span>).&lt;span style="color:#a6e22e">Decode&lt;/span>(&lt;span style="color:#a6e22e">target&lt;/span>)
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Son olarak burada üstteki Span&amp;rsquo;imiz için 2 child Span daha oluşturduk, birinde GitHub API&amp;rsquo;ndan verinin bize ne kadar
sürede geldiğini, diğerinde ise gelen veriyi ne kadar sürede JSON&amp;rsquo;a parse ettiğimizi tuttuk ve yine bir kaç &lt;code>attribute&lt;/code>
ve &lt;code>event&lt;/code> ekledik.&lt;/p>
&lt;p>Günün sonunda toplam 4 farklı işlemin kaydını tutmuş olduk, bunları listelemek gerekirse;&lt;/p>
&lt;ul>
&lt;li>Tüm işlemin ne kadar sürdüğü (root)
&lt;ul>
&lt;li>GitHub API&amp;rsquo;ndan verinin bize ne kadar sürede geldiği (child)&lt;/li>
&lt;li>Verinin ne kadar sürede JSON&amp;rsquo;a parse ettiğimiz (child)&lt;/li>
&lt;li>İşlenmiş veriyi ekrana ne kadar sürede yazdırdığımız (child)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="result">Sonuç&lt;/h2>
&lt;p>&lt;code>go run .&lt;/code> yazarak kodlarımızı çalıştırıp, &lt;code>/run&lt;/code> endpoint&amp;rsquo;ine request attıktan sonra Cloud Trace&amp;rsquo;e girip bakıyoruz.&lt;/p>
&lt;img src="https://anxl.dev/images/open-telemetry-and-cloud-trace/run.png" alt="run endpoint" class="left" style="border-radius: 8px;" />
&lt;p>Burada net bir şekilde yazdığımız kodların çalıştığını ve önümüze sonucun yazdırıldığını görüyoruz.&lt;/p>
&lt;link rel="stylesheet" href="https://anxl.dev/css/zoom.css">
&lt;img src="https://anxl.dev/images/open-telemetry-and-cloud-trace/cloud-trace-1.png" alt="Cloud Trace 1" class="center zoom" style="border-radius: 8px;" data-zoom/>
&lt;p>Örnek olarak yaptığımız çağrıları Scatter Chart&amp;rsquo;da ve sağdaki listede açıkça görebiliyoruz. Aslında buradan bile basit
bir çıkarım yapabiliriz. İlk yaptığımız çağrı &lt;em>435ms&lt;/em> sürerken, daha sonra ki çağrıların &lt;em>53ms&lt;/em>&amp;lsquo;e kadar düştüğünü görüyoruz.
Buradan ilk attığımız istekte, istediğimiz verinin veya bizim credentials&amp;rsquo;larımızın GitHub&amp;rsquo;ın önbelleğinde olmadığının
çıkarımını yapıyoruz ve bunu doğrulamak için Span&amp;rsquo;leri birbirleri ile karşılaştırıyoruz.&lt;/p>
&lt;p>Sonra karşımıza şöyle bir tablo çıkıyor;&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>request total (/run)&lt;/th>
&lt;th>fetch json&lt;/th>
&lt;th>parse json&lt;/th>
&lt;th>write&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>434.984ms&lt;/td>
&lt;td>433.595ms&lt;/td>
&lt;td>1.18ms&lt;/td>
&lt;td>0.017ms&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>53.129ms&lt;/td>
&lt;td>52.646ms&lt;/td>
&lt;td>0.374ms&lt;/td>
&lt;td>0.018ms&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Bu tablodanda anlıyacağınız üzere, &lt;code>fetch json&lt;/code> işlemi üstte dediğimiz sebepten ötürü yaklaşık 8 kat daha uzun sürüyor.
Daha sonraki request&amp;rsquo;lerde bu süre düşüyor. &lt;code>parse json&lt;/code> ve &lt;code>write&lt;/code> işlemleri kısmen yakın görünüyor. Buda gecikmenin
&lt;code>fetch json&lt;/code> işleminden kaynaklandığını tekrardan doğruluyor.&lt;/p>
&lt;link rel="stylesheet" href="https://anxl.dev/css/zoom.css">
&lt;img src="https://anxl.dev/images/open-telemetry-and-cloud-trace/cloud-trace-2.png" alt="Cloud Trace 2" class="center zoom" style="border-radius: 8px;" data-zoom/>
&lt;p>Evet yine burada görebileceğiniz üzere, root Span&amp;rsquo;e bastığımız zaman bize hangi işlemin
ne kadar sürdüğünü, eventleri ile birlikte gösteriyor. Ayrıca kodumuzda belirttiğimiz tüm attribute&amp;rsquo;ler sağ altta bulunan &lt;strong>Labels&lt;/strong> kısmında da bu tablodaki gibi gözüküyor;&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Label&lt;/th>
&lt;th>Value&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>golang.go.repo.name&lt;/td>
&lt;td>golang/go&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>golang.go.repo.id&lt;/td>
&lt;td>23096959&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>golang.go.repo.star&lt;/td>
&lt;td>86023&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>service.version&lt;/td>
&lt;td>1.0.0&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>instance.id&lt;/td>
&lt;td>foo12345&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>g.co/agent&lt;/td>
&lt;td>opentelemetry-go 0.20.0; google-cloud-trace-exporter 0.20.0&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Böylece Span hakkında daha fazla bilgi edinip, servisimizin olağındışı çalışması durumunda olayı daha kolay anlayabiliyoruz.&lt;/p>
&lt;p>Bu yapıyı biraz daha geliştirip, HTTP, gRPC gibi server&amp;rsquo;larımıza middleware exporter&amp;rsquo;lar koyup bu veriyi daha da detaylandırabilir,
yine distributed bir şekilde Span&amp;rsquo;lerle loglarımızı ilişkilendirebiliriz.&lt;/p>
&lt;hr>
&lt;h2 id="conclusion">Son&lt;/h2>
&lt;p>Günün sonunda dağıtılmış bir sistemi Cloud Trace ve OpenTelemetry ile Tracer, Span gibi yapılar kullanarak adım adım
izleyebildiğimizi ve bunları görselleştirip, yapılan çağrıların ve işlemlerin ne kadar sürdüğünü görebildiğimizi
öğrendik. Ayrıca Span&amp;rsquo;leri birbirleri ile karşılaştırıp servisimizin yavaş kaldığı noktaları bulup buraları optimize
edebileceğimizi de görmüş olduk. OpenTelemetry&amp;rsquo;nin mantığını anladıktan sonra bunu sadece Go ile değil tüm dillerde
rahatça kullanabileceğinizi unutmayın.&lt;/p>
&lt;p>Konuyu elimden geldiğince açık ve net anlatmaya çalıştım. Umarım yazıyı beğenmiş ve bir şeyler öğrenebilmişsinizdir. Bir
sonraki yazılarda görüşmek dileğiyle.&lt;/p>
&lt;p>Yazdığımız kodlara ulaşmak için: &lt;a href="https://github.com/anilmisirlioglu/blog-samples/tree/master/open-telemetry-and-cloud-trace">Github&lt;/a>&lt;/p>
&lt;hr>
&lt;h2 id="keep-learning">Öğrenmeye Devam Edin&lt;/h2>
&lt;p>Öğrenmeye devam etmek isteyenler için konu ile ilgili bir kaç bağlantı.&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://github.com/open-telemetry/opentelemetry-specification">https://github.com/open-telemetry/opentelemetry-specification&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://opentelemetry.io/docs">https://opentelemetry.io/docs&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://cloud.google.com/trace/docs/setup">https://cloud.google.com/trace/docs/setup&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://opentracing.io/docs/best-practices">https://opentracing.io/docs/best-practices&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://opentracing.io/docs/overview">https://opentracing.io/docs/overview&lt;/a>&lt;/li>
&lt;/ul></content></item></channel></rss>