CINXE.COM

Google Open Source Blog: August 2020

<!DOCTYPE html> <html class='v2 no-js' dir='ltr' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:data='http://www.google.com/2005/gml/data' xmlns:expr='http://www.google.com/2005/gml/expr'> <head> <link href='https://www.blogger.com/static/v1/widgets/3566091532-css_bundle_v2.css' rel='stylesheet' type='text/css'/> <!-- Google Tag Manager --> <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-5CNC9X8');</script> <!-- End Google Tag Manager --> <meta charset='utf-8'/> <meta content='IE=Edge' http-equiv='X-UA-Compatible'/> <meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, height=device-height' name='viewport'/> <link href='https://opensource.google.com/assets/static/images/favicon.png' rel='shortcut icon'/> <meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/> <meta content='blogger' name='generator'/> <link href='https://opensource.googleblog.com/favicon.ico' rel='icon' type='image/x-icon'/> <link href='https://opensource.googleblog.com/2020/08/' rel='canonical'/> <link rel="alternate" type="application/atom+xml" title="Google Open Source Blog - Atom" href="https://opensource.googleblog.com/feeds/posts/default" /> <link rel="alternate" type="application/rss+xml" title="Google Open Source Blog - RSS" href="https://opensource.googleblog.com/feeds/posts/default?alt=rss" /> <link rel="service.post" type="application/atom+xml" title="Google Open Source Blog - Atom" href="https://www.blogger.com/feeds/8698702854482141883/posts/default" /> <!--Can't find substitution for tag [blog.ieCssRetrofitLinks]--> <meta content='https://opensource.googleblog.com/2020/08/' property='og:url'/> <meta content='Google Open Source Blog' property='og:title'/> <meta content='' property='og:description'/> <title>Google Open Source Blog: August 2020</title> <meta content='Google Open Source Blog' property='twitter:title'/> <meta content='https://opensource.google.com/assets/static/images/home/blog/blog_image_1.jpg' property='og:image'/> <meta content='en_US' property='og:locale'/> <meta content='Google Open Source Blog' property='og:site_name'/> <meta content='summary' name='twitter:card'/> <meta content='@GoogleOSS' name='twitter:creator'/> <meta content='@GoogleOSS' name='twitter:site'/> <style id='page-skin-1' type='text/css'><!-- --></style> <style id='template-skin-1' type='text/css'><!-- body { min-width: 860px; } .content-outer, .content-fauxcolumn-outer, .region-inner { min-width: 860px; max-width: 860px; _width: 860px; } .main-inner .columns { padding-left: 0px; padding-right: 260px; } .main-inner .fauxcolumn-center-outer { left: 0px; right: 260px; /* IE6 does not respect left and right together */ _width: expression(this.parentNode.offsetWidth - parseInt("0px") - parseInt("260px") + 'px'); } .main-inner .fauxcolumn-left-outer { width: 0px; } .main-inner .fauxcolumn-right-outer { width: 260px; } .main-inner .column-left-outer { width: 0px; right: 100%; margin-left: -0px; } .main-inner .column-right-outer { width: 260px; margin-right: -260px; } #layout { min-width: 0; } #layout .content-outer { min-width: 0; width: 800px; } #layout .region-inner { min-width: 0; width: auto; } body#layout div.add_widget { padding: 8px; } body#layout div.add_widget a { margin-left: 32px; } --></style> <script type='text/javascript'> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-53341410-4', 'auto', 'blogger'); ga('blogger.send', 'pageview'); </script> <link href='https://fonts.googleapis.com/css?family=Google+Sans|Roboto+Slab:300,500,900|Roboto:400italic,400,500,500italic,700,700italic' rel='stylesheet'/> <link href='https://fonts.googleapis.com/icon?family=Material+Icons' rel='stylesheet'/> <!-- OGC styles with data uri --> <style type='text/css'> .footer-main .google a { background: url("data:image/svg+xml,%3C%3Fxml%20version%3D%271.0%27%20encoding%3D%27utf-8%27%3F%3E%0A%3Csvg%20version%3D%271.1%27%20id%3D%27content%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20xmlns%3Axlink%3D%27http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%27%20x%3D%270px%27%20y%3D%270px%27%0A%09%20viewBox%3D%270%200%20416%20139.5%27%20style%3D%27enable-background%3Anew%200%200%20416%20139.5%3B%27%20xml%3Aspace%3D%27preserve%27%3E%0A%3Cstyle%20type%3D%27text%2Fcss%27%3E%0A%09.st0%7Bfill%3A%23FFFFFF%3B%7D%0A%3C%2Fstyle%3E%0A%3Csymbol%20%20id%3D%27logo_x5F_dark%27%20viewBox%3D%270.7%20-135.4%20414.8%20135.3%27%3E%0A%09%3Cpath%20class%3D%27st0%27%20d%3D%27M0.7-52.6C0.7-23.6%2C25-0.1%2C54-0.1c16%2C0%2C27.4-6.3%2C36-14.5L79.8-24.7C73.7-18.9%2C65.4-14.4%2C54-14.4%0A%09%09c-21.1%2C0-37.6-17-37.6-38.1c0-21.1%2C16.5-38.1%2C37.6-38.1c13.7%2C0%2C21.5%2C5.5%2C26.5%2C10.5c4.1%2C4.1%2C6.8%2C10%2C7.8%2C18H54v14.3h48.3%0A%09%09c0.5-2.6%2C0.8-5.6%2C0.8-9c0-10.8-2.9-24.1-12.4-33.5C81.4-99.9%2C69.6-105%2C54-105C25-105%2C0.7-81.5%2C0.7-52.6z%27%2F%3E%0A%09%3Cpath%20class%3D%27st0%27%20d%3D%27M142-37.5c-18.7%2C0-33.9-14.2-33.9-33.8c0-19.5%2C15.2-33.8%2C33.9-33.8c18.7%2C0%2C33.9%2C14.3%2C33.9%2C33.8%0A%09%09C175.9-51.7%2C160.7-37.5%2C142-37.5z%20M142-91.7c-10.2%2C0-19.1%2C8.4-19.1%2C20.5c0%2C12.2%2C8.8%2C20.5%2C19.1%2C20.5c10.2%2C0%2C19.1-8.3%2C19.1-20.5%0A%09%09C161.1-83.3%2C152.2-91.7%2C142-91.7z%27%2F%3E%0A%09%3Cpath%20class%3D%27st0%27%20d%3D%27M216-37.5c-18.7%2C0-33.9-14.2-33.9-33.8c0-19.5%2C15.2-33.8%2C33.9-33.8c18.7%2C0%2C33.9%2C14.3%2C33.9%2C33.8%0A%09%09C249.9-51.7%2C234.7-37.5%2C216-37.5z%20M216-91.7c-10.2%2C0-19.1%2C8.4-19.1%2C20.5c0%2C12.2%2C8.8%2C20.5%2C19.1%2C20.5s19.1-8.3%2C19.1-20.5%0A%09%09C235.1-83.3%2C226.2-91.7%2C216-91.7z%27%2F%3E%0A%09%3Cpath%20class%3D%27st0%27%20d%3D%27M306.8-39.5V-45h-0.5c-3.3%2C4-9.7%2C7.6-17.8%2C7.6c-16.9%2C0-32.4-14.8-32.4-33.9c0-18.9%2C15.5-33.7%2C32.4-33.7%0A%09%09c8.1%2C0%2C14.5%2C3.6%2C17.8%2C7.7h0.5v-4.9c0-12.9-6.9-19.8-18-19.8c-9.1%2C0-14.7%2C6.5-17%2C12l-12.9-5.4c3.7-9%2C13.6-20%2C30-20%0A%09%09c17.4%2C0%2C32.1%2C10.2%2C32.1%2C35.2v60.7H306.8z%20M289.8-91.7c-10.2%2C0-18.8%2C8.6-18.8%2C20.4c0%2C11.9%2C8.6%2C20.6%2C18.8%2C20.6c10.1%2C0%2C18-8.7%2C18-20.6%0A%09%09C307.9-83.2%2C299.9-91.7%2C289.8-91.7z%27%2F%3E%0A%09%3Crect%20x%3D%27331.2%27%20y%3D%27-103%27%20class%3D%27st0%27%20width%3D%2714.8%27%20height%3D%2799.3%27%2F%3E%0A%09%3Cpath%20class%3D%27st0%27%20d%3D%27M386.7-91.7c-7.6%2C0-12.9%2C3.5-16.4%2C10.2l45.2%2C18.7L414-59c-2.8%2C7.6-11.4%2C21.5-28.9%2C21.5%0A%09%09c-17.4%2C0-31.9-13.7-31.9-33.8c0-18.9%2C14.3-33.8%2C33.5-33.8c15.5%2C0%2C24.4%2C9.5%2C28.2%2C15l-11.5%2C7.7C399.5-88%2C394.3-91.7%2C386.7-91.7z%0A%09%09%20M385.6-50.5c5.9%2C0%2C10.9-2.9%2C12.5-7.2l-30.2-12.5C367.5-57.2%2C378-50.5%2C385.6-50.5z%27%2F%3E%0A%3C%2Fsymbol%3E%0A%3Cuse%20xlink%3Ahref%3D%27%23logo_x5F_dark%27%20%20width%3D%27414.8%27%20height%3D%27135.3%27%20id%3D%27XMLID_1_%27%20x%3D%270.7%27%20y%3D%27-135.4%27%20transform%3D%27matrix(1%200%200%20-1%200%201)%27%20style%3D%27overflow%3Avisible%3B%27%2F%3E%0A%3C%2Fsvg%3E%0A") 0 0 no-repeat; } </style> <!-- OGC styles --> <style type='text/css'> #ogc-shim { display: none; visibility: hidden; } body { background-color: white; color: #444; font-family: "Roboto", sans-serif; min-width: 300px; line-height: 18px; margin: 0; padding: 0; -webkit-font-smoothing: antialiased; } body .container { overflow-x: hidden; } body a { color: #4285f4; font-weight: 500; text-decoration: none; } body div, body p, body ol { color: #444; font-size: 16px; line-height: 22px; margin: 0 0 33px 0; } body div { margin: 0; } body h1 { color: #444; font-family: "Roboto",sans-serif; font-size: 34px; font-weight: 300; line-height: 44px; margin: 0 0 33px 0; padding: 0; } body h1, body h2, body h3, body h4, body h5, body h6 { color: #444; font-family: "Google Sans",sans-serif; letter-spacing: -.01em; font-size: 34px; font-weight: 400; line-height: 44px; margin: 0 0 33px 0; padding: 0; } body ul { list-style: none; margin: 0; padding: 0; } body #whatbrowser { background: white; height: 100%; padding: 50px 15px; position: fixed; width: 100%; z-index: 300; } .header-main { background-color: #ffffff; height: 75px; line-height: 75px; position: relative; } .header-main a { color: #4c4c4c; text-decoration: none; } .header-main h1 { margin: 21px -250px 0 0; position: absolute; right: 100%; text-indent: -9999px; transition: all 0.3s ease-out; } .header-main h1 a { /* background: url(https://opensource.google.com/assets/static/images/logo_dark.svg) 0 0 no-repeat; */ background: url(https://www.gstatic.com/devrel-devsite/stage/v93a6dcf50ad5e38e51034415df5b4a8345b5c8613f785e48818ae468dabf73c8/opensource/images/lockup.svg) 0 0 no-repeat; background-size: 240px auto; display: block; height: 32px; line-height: 75px; width: 240px; } .nav-active { overflow: hidden; position: fixed; } .nav-active .main-nav { transform: translate(0, 0); } .nav-active #ShadowBox { display: block; } #ShadowBox { background: rgba(51,51,51,0.8); content: '[]'; display: none; height: 100vh; left: 0; position: absolute; text-indent: -9999px; top: 0; width: 100vw; z-index: 98; } .main-nav { background: #ffffff; height: 100vh; list-style: none; margin: 0; overflow: scroll; padding: 0; position: fixed; right: 0; top: 75px; transform: translate(277px, 0); transition: transform 0.2s ease-in; width: 277px; z-index: 300; } .main-nav ul { border-top: solid 4px #f2f2f2; min-height: 360px; padding-top: 10px; } .main-nav ul li { line-height: 55px; } .main-nav ul li a { background: white; display: block; font-size: 14px; padding: 0 30px; } .main-nav ul li a:hover, .main-nav ul li a:focus { color: #4285f4; } #NavTrigger { height: 48px; padding-top: 27px; position: absolute; right: 0; text-align: left; top: 0; width: 40px; } #NavTrigger:before, #NavTrigger:after, #NavTrigger span { background: #4c4c4c; border-radius: 50%; content: '.'; height: 4px; line-height: 4px; margin: 2px auto; width: 4px; display: block; overflow: hidden; text-indent: -9999px; } .main { background-color: #ffffff; box-shadow: 0 1px 1.5px rgba(0,0,0,0.12), 0 1px 1px rgba(0,0,0,0.24); box-sizing: border-box; margin: 0 auto; min-height: 100vh; } .col-wrap { margin: 0 auto; max-width: 988px; width: 100%; } .col-wrap:after { clear: both; content: ""; display: table; } .google-open-source { text-align: center; } .google-open-source .content { text-align: left; } .google-open-source .cols-wrapper { text-align: left; } .google-open-source section { padding: 35px 15px 15px 15px; } div.section#header { margin: inherit; } div.widget#Header1 { margin: inherit; line-height: inherit; } section.hero { background-color: #F8F9FA; box-sizing: border-box; color: #202124; display: flex; flex-direction: column; height: 338px; min-height: 338px; justify-content: center; margin: 0 auto; padding: 15px; position: relative; text-align: left; -ms-flex-align: center; } .hero:after { background: url("https://opensource.google.com/assets/static/images/home/hero-tall-mobile.png") 0 0 no-repeat; background-size: 257px 393px; content: '.'; font-size: 0; height: 393px; left: -15px; position: absolute; top: 0; width: 257px; } .short + .hero { height: 100%; min-height: 300px; } .short + .hero:after { display: none; } .short + .hero .col { display: -ms-flexbox; display: flex; flex-direction: column; height: 300px; justify-content: center; -ms-flex-align: center; } .short + .hero h2, .short + .hero h2 a { text-align: left !important; font-size: 56px !important; line-height: 48px !important; margin-bottom: 40px !important; color: #202124 !important; font-family: "Google Sans", sans-serif; text-decoration: none; } .short + .hero p { color: #202124; font-family: "Google Sans", sans-serif; font-size: 16px; line-height: 21px; margin-bottom: 0; max-width: 700px; z-index: 1; position: relative; } .hero h2 { color: #202124; margin: 0 0 8px 0; } .google-open-source section.hero h2 { font-size: 34px; line-height: 40px; margin-bottom: 20px; } .google-open-source section.hero h2.logo { background-size: 290px 36px; display: block; font-size: 0; height: 36px; text-indent: -9999px; width: 290px; } .hero p { color: #202124; font-family: "Roboto",sans-serif; font-size: 24px; line-height: 32px; } .hero .col-wrap { display: block !important; max-width: 1200px; } .google-open-source section p { font-size: 16px; margin: 0 auto 30px auto; } h2.archive-header { font-size: 32px; line-height: 40px; margin-bottom: 16px; } .google-open-source .main-inner .column-center-inner { padding: 0 15px 0 0; } .google-open-source .main-inner .column-center-inner .section { margin: 0 15px 0 0; } /*.google-open-source section.hero p { font-size: 18px; line-height: 24px; margin: 0; max-width: 240px; }*/ .post-footer .share { text-align: right; margin-bottom: 1em; } .post-footer .share img { margin-left: 12px; } .fb-custom img, .twitter-custom img, .gplus-share img { opacity: 0.54; cursor: pointer; } .fb-custom:hover img, .fb-custom:focus img, .twitter-custom:hover img, .twitter-custom:focus img, .gplus-share:hover img, .gplus-share:focus img { opacity: 1; } .footer-main { background-color: #474747; box-sizing: border-box; color: #ffffff; padding: 24px 15px; position: relative; z-index: 98; } .footer-main .col-wrap { max-width: none; } .footer-main nav li { display: inline-block; line-height: 25px; margin: 0 15px 0 0; } .footer-main a { color: #ccc; font-size: 14px; text-decoration: none; text-transform: uppercase; } .footer-main a:hover, .footer-main a:focus { color: white; } .footer-main .google { display: block; margin-bottom: 15px; } .footer-main .google a { display: inline-block; height: 26px; opacity: 0.54; text-indent: -9999px; width: 80px; } .pull-left { float: left; } @media (min-width: 720px) { body h1, body h2 { font-size: 44px; line-height: 54px; } .main-nav { float: right; height: 48px; overflow: hidden; position: inherit; top: -14px; transform: translate(0, 0); width: auto; right: unset; left: 350px; } .main-nav ul { border: none; padding: 0; } .main-nav ul li { display: inline-block; line-height: 48px; margin: 0 15px 0 0; } .main-nav ul li a { display: inline-block; padding: 0; } #NavTrigger { display: none; } .google-open-source section.hero { text-align: left; } body .hero:before { background: url(https://opensource.google/images/featured-blogs-icon.svg) 0px 0 no-repeat; background-size: 575px 85px; background-position-y: center; content: '.'; display: block; height: 100%; position: absolute; right: -10px; text-indent: -99999px; top: 0; width: 635px; } .short + .hero { height: 300px; } .google-open-source section.hero h2 { font-size: 46px; line-height: 52px; } .google-open-source section.hero h2.logo { background-size: 582px 72px; float: right; font-size: 0; height: 72px; width: 582px; } .google-open-source section p { max-width: 642px; } .google-open-source section.hero p { margin: 0 0 0px 0; } .footer-main nav .google { display: inline-block; margin-bottom: 0; } .header-main { height: 48px; } .header-main h1 { margin: 8px -265px 0 0; } .main.google-open-source { margin-top: 48px !important; } } @media (min-width: 940px) { body h1, body h2 { font-size: 52px; } .main-nav ul li { margin: 0 36px 0 0; } section.hero { opacity: 1; height: 600px; transition: opacity 0.4s ease-in; } /*body.item .hero:before, */ body.archive .hero:before { background-position: 0 0; } .hero h2 { opacity: 1; transition: opacity 0.4s ease-in 0.4s; } .google-open-source section.hero h2 { font-size: 52px; line-height: 58px; } .google-open-source .hero h2, .google-open-source .hero p { position: relative; } .google-open-source .hero h2:before, .google-open-source .hero p:before, .google-open-source .hero p:after { background: #474747; /*content: '|';*/ /* XXX not sure why this borks here, but works on OGC. or why it's necessary on OGC */ position: absolute; width: 100%; height: 100px; right: 0; text-indent: 99999px; transition: width 0.5s ease-in; } .google-open-source .hero h2:before { transition-delay: 0.5s; width: 87%; } .google-open-source .hero p:before, .google-open-source .hero p:after { height: 31px; transition-duration: 0.5s; transition-delay: 1s; } .google-open-source .hero p:after { transition-delay: 1.4s; } .google-open-source .hero:after { display: none; } .line-graphic { height: 600px; left: 0; position: absolute; top: 0; width: 100%; } .line-graphic .segment { width: 0; position: absolute; transition: width 0.25s ease-in; transition-delay: 1s; } .line-graphic .hotspot { height: 0; opacity: 0; transform: scale(1); transition: all 0.5s ease-in; transition-delay: 1 + 0.15s * 12; width: 0; } .line-graphic .hotspot:after { pointer-events: none; } .js .hero, .js .hero h2 { opacity: 1; } .js .hero h2:before, .js .hero p:before, .js .hero p:after { width: 0; } .js .line-graphic .blue-one { background: url("https://opensource.google.com/assets/static/images/home/hero/blue-1.png") 0 0 no-repeat; background-size: 381px 33px; width: 381px; height: 33px; top: 111px; left: -15px; transition-delay: 1 + 0.15s * 6; transition-duration: 0.25s * 2; } .js .line-graphic .grey-one { background: url("https://opensource.google.com/assets/static/images/home/hero/grey-1.png") 0 0 no-repeat; background-size: 232px 38px; width: 232px; height: 38px; top: 79px; left: 111px; transition-delay: 1 + 0.15s * 7; transition-duration: 0.25s * 1.5; } .js .line-graphic .grey-two { background: url("https://opensource.google.com/assets/static/images/home/hero/grey-2.png") 0 0 no-repeat; background-size: 100px 18px; width: 100px; height: 18px; top: 224px; left: -15px; transition-delay: 1 + 0.15s * 2; } .js .line-graphic .yellow-one { background: url("https://opensource.google.com/assets/static/images/home/hero/yellow-1.png") 0 0 no-repeat; background-size: 253px 21px; width: 253px; height: 21px; top: 322px; left: -15px; transition-delay: 1 + 0.15s * 3; } .js .line-graphic .grey-three { background: url("https://opensource.google.com/assets/static/images/home/hero/grey-3.png") 0 0 no-repeat; background-size: 100px 101px; width: 100px; height: 101px; top: 222px; left: 78px; transition-delay: 1 + 0.15s * 4; } .js .line-graphic .red-one { background: url("https://opensource.google.com/assets/static/images/home/hero/red-1.png") 0 0 no-repeat; background-size: 358px 49px; width: 358px; height: 49px; top: 139px; left: -15px; transition-delay: 1 + 0.15s * 6; transition-duration: 0.25s * 2; } .js .line-graphic .grey-four { background: url("https://opensource.google.com/assets/static/images/home/hero/grey-4.png") 0 0 no-repeat; background-size: 143px 49px; width: 143px; height: 49px; top: 340px; left: 78px; transition-delay: 1 + 0.15s * 6; } .js .line-graphic .green-one { background: url("https://opensource.google.com/assets/static/images/home/hero/green-1.png") 0 0 no-repeat; background-size: 251px 86px; width: 251px; height: 86px; top: 387px; left: 202px; transition-delay: 1 + 0.15s * 7; } .js .line-graphic .blue-two { background: url("https://opensource.google.com/assets/static/images/home/hero/blue-2.png") 0 0 no-repeat; background-size: 323px 25px; width: 323px; height: 25px; position: absolute; top: 115px; left: 371px; transition-delay: 1 + 0.15s * 10; } .js .line-graphic .grey-five { background: url("https://opensource.google.com/assets/static/images/home/hero/grey-5.png") 0 0 no-repeat; background-size: 141px 53px; width: 141px; height: 53px; top: 466px; left: 282px; transition-delay: 1 + 0.15s * 9; } .js .line-graphic .grey-six { background: url("https://opensource.google.com/assets/static/images/home/hero/grey-6.png") 0 0 no-repeat; background-size: 178px 118px; width: 178px; height: 118px; top: 0; left: 497px; transition-delay: 1 + 0.15s * 11; } .js .line-graphic .green-two { background: url("https://opensource.google.com/assets/static/images/home/hero/green-2.png") 0 0 no-repeat; background-size: 276px 142px; width: 276px; height: 142px; top: 515px; left: 394px; transition-delay: 1 + 0.15s * 11; } .js .line-graphic .grey-seven { background: url("https://opensource.google.com/assets/static/images/home/hero/grey-7.png") 0 0 no-repeat; background-size: 174px 93px; width: 174px; height: 93px; margin-left: -174px; top: 0; left: 100%; transition-delay: 1 + 0.15s * 12; } .js .line-graphic .grey-eight { background: url("https://opensource.google.com/assets/static/images/home/hero/grey-8-interactive.png") 0 0 no-repeat; background-size: 184px 17px; width: 184px; height: 17px; top: 23px; left: 681px; transition-delay: 0s; } .js .line-graphic .yellow-two { background: url("https://opensource.google.com/assets/static/images/home/hero/yellow-2-interactive.png") 0 0 no-repeat; background-size: 140px 25px; width: 140px; height: 25px; top: 319px; left: 244px; transition-delay: 0s; } .js .line-graphic .hidden { width: 0; } .js .line-graphic .hotspot { height: 40px; position: absolute; top: 12px; left: 645px; opacity: 1; transform: scale(1); width: 40px; } .js .line-graphic .hotspot::after { content: 'o'; display: block; background: $color-grey; border-radius: 50%; width: 40px; height: 40px; opacity: 0.4; text-indent: 9999px; animation: pulse 3.5s infinite; animation-delay: 0.5s; } .js .line-graphic .hotspot.yellow { top: 312px; left: 210px; } .js .line-graphic .hotspot.yellow::after { background: #fabb05; animation-delay: 0s; } @keyframes pulse { 0% { opacity: 0.3; transform: scale(1); } 20% { opacity: 0.1; transform: scale(0.3); } 80% { opacity: 0.1; transform: scale(0.3); } 100% { opacity: 0.3; transform: scale(1); } } .footer-main { padding: 24px; } } </style> <!-- OGC sticky header --> <style type='text/css'> .header-main { position: fixed; top: 0; width: 100%; box-shadow: 0 0 4px rgba(0,0,0,.14), 0 4px 8px rgba(0,0,0,.28); z-index: 200; } .main.google-open-source { margin-top: 75px; z-index: 100; } </style> <!-- OGC blog content and sidebar styles --> <style type='text/css'> body .sidebar .widget div { font-size: 16px; } .sidebar .searchBox input { border: 1px solid #eee; color: #212121; color: rgba(0,0,0,.87); font-size: 16px; padding: 8px 8px 8px 40px; width: 150px; font-family: Roboto, sans-serif; background: url(https://www.gstatic.com/images/icons/material/system/1x/search_grey600_24dp.png) 8px center no-repeat; } .sidebar .subscribe h2 { margin-bottom: 0 !important; } .sidebar .popular-posts ul { padding: 0; } .sidebar .popular-posts ul li { padding: 0 0 1em 0 !important; } .sidebar-icon { display: inline-block; height: 24px; width: 24px; vertical-align: middle; margin-right: 12px; margin-top: -1px; } .sidebar .subscribe img { opacity: 0.54; } .sidebar .share img { margin-right: 12px; opacity: 0.54; } .sidebar .share a:hover img, .sidebar .share a:focus img, .sidebar .subscribe:hover img, .sidebar .subscribe:focus img { opacity: 1; } .sidebar .widget { margin: 0; padding: 15px 0; min-height: 20px; border-bottom: 1px solid #eee; } .sidebar.section:first-child .widget:first-child { border-bottom: 0; } .sidebar.section:last-child .widget:last-child { border-bottom: 0; } .sidebar .widget a { font-weight: 100; color: #444; } .sidebar .widget a:focus, .sidebar .widget a:hover { color: #4285f4; } .sidebar .widget h2 { color: #444; font-family: "Google Sans", sans-serif; padding-bottom: 3px; font-size: 18px; line-height: 24px; margin-bottom: 16px; font-weight: 500; display: inline-block; text-decoration: none; } .widget.PopularPosts h2:before { content: url(https://www.gstatic.com/images/icons/material/system/1x/star_grey600_24dp.png); position: relative; top: 5px; padding: 0 10px 0 0; } .sidebar .student_programs { text-align: center; font-size: 14px !important; } .widget.PopularPosts ul li:last-child { padding-bottom: 5px !important; } .widget.BlogArchive { padding-bottom: 0px !important; } .widget.BlogArchive .widget-content { display: none; } .widget.BlogArchive h2 { display: block !important; cursor: pointer; } .widget.BlogArchive h2:before { content: url(https://www.gstatic.com/images/icons/material/system/1x/folder_grey600_24dp.png); position: relative; top: 5px; padding: 0 10px 0 0; } .widget.BlogArchive h2:after { content: url(https://www.gstatic.com/images/icons/material/system/1x/keyboard_arrow_down_grey600_24dp.png); position: absolute; right: 0; top: 7px; } .widget.BlogArchive.active h2:after { content: url(https://www.gstatic.com/images/icons/material/system/1x/keyboard_arrow_up_grey600_24dp.png); } #ArchiveList .toggle { float: right; color: rgba(0,0,0, 0.54) !important; } .BlogArchive #ArchiveList ul li { padding-left: 0px !important; text-indent: 0px !important; } .BlogArchive .post-count { color: #444; } .BlogArchive .post-count-link:hover { color: #444 !important; } .BlogArchive .intervalToggle { cursor: pointer; } .BlogArchive .expanded .intervalToggle .new-toggle { -ms-transform: rotate(180deg); transform: rotate(180deg); } .BlogArchive .new-toggle { float: right; padding-top: 3px; opacity: 0.87; } #ArchiveList .expanded > ul:last-child { margin-bottom: 16px; } #ArchiveList .archivedate { width: 100%; } .content-outer, .region-inner { /* min-width is 860, should be 300 to accommodate mobile */ position: relative; max-width: 988px; margin: 0 auto; } .date-outer + .date-outer, .post-footer + .post-outer { margin-top: 33px; padding-top: 33px; } pre.prettyprint { white-space: pre-wrap; } h4.date-header { color: #474747; font-size: 16px; line-height: 16px; font-weight: 100; font-family: "Google Sans", sans-serif; } h3.post-title { font-family: "Google Sans", sans-serif; font-size: 28px; line-height: 40px; margin-bottom: 16px; font-weight: 400; } body h3.post-title a { font-weight: 400; } .post .post-body { font-size: 16px; line-height: 1.5em; } .post-body img { max-width: 100%; height: auto; } div.separator a { max-width: 50%; } .post .post-body h2, .post .post-body h3, .post .post-body h4 { margin: 1em 0; } .post .post-body h2 { font-size: 24px; line-height: 24px; } .post .post-body h3 { font-size: 20px; line-height: 20px; } .post .post-body h4 { font-size: 16px; line-height: 16px; } .post .post-body p { max-width: inherit; margin: 1em 0; line-height: 1.5em; } .post .post-body ol, .post .post-body ul { margin: 1em 0; } .post .post-body ul { list-style-type: disc; } .post .post-body blockquote { font-style: italic; } .post .post-body pre, .post .post-body code { line-height: 1.25em; display: block; margin: 1em 0; } .post .post-body .intrinsic-container { position: relative; height: 0; overflow: hidden; } /* 16x9 Aspect Ratio */ .post .post-body .intrinsic-container-16x9 { padding-bottom: 56.25%; } /* 4x3 Aspect Ratio */ .post .post-body .intrinsic-container-4x3 { padding-bottom: 75%; } .post .post-body .intrinsic-container iframe { position: absolute; top:0; left: 0; width: 100%; height: 100%; } .post .post-body table.tr-caption-container[style*="float: right"], .post .post-body table.tr-caption-container[style*="float:right"], .post .post-body table.tr-caption-container[style*="float: left"], .post .post-body table.tr-caption-container[style*="float:left"] { width: auto; display: inline-block; } .post .post-body table { margin: 1em 0; width: 100%; } .post .post-body table thead { vertical-align: top; font-weight: 900; } .post .post-body table tbody { vertical-align: top; font-size: 14px; } .post .post-body table .tr-caption { text-align: center; font-style: italic; font-size: 14px; } div.post-footer { margin-top: 33px; } /* Home, forward, and backward pagination. */ .blog-pager { border-top : 1px #e0e0e0 solid; padding-top: 10px; margin-top: 15px; text-align: right !important; } #blog-pager { margin-botom: 0; margin-top: -14px; padding: 16px 0 0 0; } #blog-pager a { display: inline-block; } .blog-pager i.disabled { opacity: 0.2 !important; } .blog-pager i { color: black; margin-left: 16px; opacity: 0.54; } .blog-pager i:hover, .blog-pager i:active { opacity: 0.87; } #blog-pager-older-link, #blog-pager-newer-link { float: none; } #blog-pager { margin: 0; padding: 16px 0; } .list-page #blog-pager { padding-top: 0; border: 0; margin-top: -8px; } .labels-caption { font-weight: 500; } .labels a { font-weight: 100; } .label-footer { margin-bottom: 12px; margin-top: 12px; } @media (max-width: 720px) { .column-right-outer { display: none; } .content-outer, .region-inner { min-width: 300px; } .main-inner .columns { padding-right: inherit; } } </style> <style type='text/css'> .gci_winner_table, .table1 { border-collapse: collapse; border: none; text-align: left; } .gci_winner_table td, .gci_winner_table th, .table1 td, .table1 th { border: 1px solid #999999; } .gci_winner_table thead td, .gci_winner_table thead th, .table1 thead td, .table1 thead th { background-color: #d0e0e3; font-weight: 900; padding: 7px 7px 7px 3px; } .gci_winner_table tbody td, .table1 tbody td { padding: 3px; } .gci_winner_table td.column_separator, .table1 td.column_separator { background-color: transparent !important; border: 0px !important; } </style> <link href='https://www.blogger.com/dyn-css/authorization.css?targetBlogID=8698702854482141883&amp;zx=a36d78d2-bbd6-4a9f-988d-87c622fed0da' media='none' onload='if(media!=&#39;all&#39;)media=&#39;all&#39;' rel='stylesheet'/><noscript><link href='https://www.blogger.com/dyn-css/authorization.css?targetBlogID=8698702854482141883&amp;zx=a36d78d2-bbd6-4a9f-988d-87c622fed0da' rel='stylesheet'/></noscript> <meta name='google-adsense-platform-account' content='ca-host-pub-1556223355139109'/> <meta name='google-adsense-platform-domain' content='blogspot.com'/> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?display=swap&family=Roboto&family=Courier&family=Roboto+Mono&family=Consolas"></head> <body class='archive'> <!-- Google Tag Manager (noscript) --> <noscript><iframe height='0' src='https://www.googletagmanager.com/ns.html?id=GTM-5CNC9X8' style='display:none;visibility:hidden' width='0'></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <a name='top'></a> <div class='container'> <!--[if lte IE 11]> <p id="whatbrowser" class="whatbrowser"> You are using an <strong>outdated</strong> browser. Please <a href="http://whatbrowser.com/" target="_blank"> upgrade your browser </a> to improve your experience. </p> <![endif]--> <header class='header-main'> <h1> <a href='https://opensource.google.com/' title='Google Open Source'> opensource.google.com </a> </h1> <a href='/#Navigation' id='NavTrigger' title='Nav Toggle Open'> <span>Menu</span> </a> <nav class='main-nav' id='Navigation'> <ul> <li class='events'> <a class='internal' href='https://opensource.google.com/events/' title='Events'> Events </a> </li> <li class='projects'> <a class='internal' href='https://opensource.google.com/projects/' title='Projects'> Projects </a> </li> <li class='programs-and-services'> <a class='internal' href='https://opensource.google/programs-and-services' title='Programs and services'> Programs and services </a> </li> <li class='docs'> <a class='internal' href='https://opensource.google/documentation/reference' title='Documentation'> Documentation </a> </li> <li class='about'> <a class='internal' href='https://opensource.google/about' title='About'> About </a> </li> <li class='blog'> <a class='internal' href='/' title='Blog'> Blog </a> </li> </ul> </nav> </header> <div class='main google-open-source'> <div class='section' id='header'><div class='widget Header' data-version='1' id='Header1'> <div class='short'></div> <section class='hero'> <div class='col-wrap'> <h2><a href='/' title='Google Open Source Blog'>Google Open Source Blog</a></h2> <p>The latest news from Google on open source releases, major projects, events, and student outreach programs.</p> </div> </section> </div></div> <section class='content'> <div class='content-outer'> <div class='region-inner main-inner'> <div class='columns'> <div class='columns-inner'> <div class='column-center-outer'> <div class='column-center-inner'> <div class='section' id='main' name='Main'><div class='widget Blog' data-version='1' id='Blog1'> <div class='blog-posts hfeed'> <div class='col-wrap'> <h2 class='archive-header'>Posts from August 2020</h2> </div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry uncustomized-post-template' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOed5QqN40nmSo9y8T8TRKMFyMONWz2lxZe-Agd2ajlXWuky0rEpKD1iZvz2xwjggLuN6FONV2ROgxGq5eNPNs7x9SOnqzNURZI8ESxzHdVL_f9wefB_NnVdYGjGsB4HeSwr0v7FgbBDU/s640/case_study_blog_post_gopher.png' itemprop='image_url'/> <meta content='8698702854482141883' itemprop='blogId'/> <meta content='1751517871088746439' itemprop='postId'/> <a name='1751517871088746439'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='https://opensource.googleblog.com/2020/08/new-case-studies-about-googles-use-of-go.html'>New Case Studies About Google&#8217;s Use of Go</a> </h3> <div class='post-header'> <h4 class='date-header'><span>Thursday, August 27, 2020</span></h4> </div> <div class='post-body entry-content' id='post-body-1751517871088746439' itemprop='description articleBody'> Go started in September 2007 when Robert Griesemer, Ken Thompson, and I began discussing a new language to address the engineering challenges we and our colleagues at Google were facing in our daily work. The software we were writing was typically a networked server&#8212;a single program interacting with hundreds of other servers&#8212;and over its lifetime thousands of programmers might be involved in writing and maintaining it. But the existing languages we were using didn't seem to offer the right tools to solve the problems we faced in this complex environment.<br /><br />So, we sat down one afternoon and started talking about a different approach.<br /><br />When we first released Go to the public in November 2009, we didn&#8217;t know if the language would be widely adopted or if it might influence future languages. Looking back from 2020, Go has succeeded in both ways: it is widely used both inside and outside Google, and its approaches to network concurrency and software engineering have had a noticeable effect on other languages and their tools.<br /><br />Go has turned out to have a much broader reach than we had ever expected. Its growth in the industry has been phenomenal, and it has powered many projects at Google.<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><img border="0" data-original-height="1161" data-original-width="2048" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOed5QqN40nmSo9y8T8TRKMFyMONWz2lxZe-Agd2ajlXWuky0rEpKD1iZvz2xwjggLuN6FONV2ROgxGq5eNPNs7x9SOnqzNURZI8ESxzHdVL_f9wefB_NnVdYGjGsB4HeSwr0v7FgbBDU/s640/case_study_blog_post_gopher.png" style="margin-left: auto; margin-right: auto;" width="640" /></td></tr><tr><td class="tr-caption" style="text-align: center;">Credit to Renee French for the gopher illustration.<br /></td></tr></tbody></table><div><br />The earliest production uses of Go inside Google appeared in 2011, the year we launched <a href="https://blog.golang.org/appengine" target="_blank">Go on App Engine</a> and started <a href="https://www.youtube.com/watch?v=midJ6b1LkA0" target="_blank">serving YouTube database traffic with Vitess</a>. At the time, Vitess&#8217;s authors told us that Go was exactly the combination of easy network programming, efficient execution, and speedy development that they needed, and that if not for Go, they likely wouldn&#8217;t have been able to build the system at all.<br /><br />The next year, <a href="http://www.unofficialgoogledatascience.com/2015/12/replacing-sawzall-case-study-in-domain.html">Go replaced Sawzall for Google&#8217;s search quality analysis</a>. And of course, Go also powered Google&#8217;s development and <a href="https://cloudplatform.googleblog.com/2014/06/an-update-on-container-support-on-google-cloud-platform.html">launch of Kubernetes in 2014</a>.<br /><br />In the past year, we&#8217;ve posted <a href="https://go.dev/solutions" target="_blank">sixteen case studies</a> from end users around the world talking about how they use Go to build fast, reliable, and efficient software at scale. Today, we are adding three new case studies from teams inside Google:<br /><ul style="text-align: left;"><li><b>Core Data Solutions:</b> Google&#8217;s <a href="https://go.dev/solutions/google/coredata" target="_blank">Core Data</a> team replaced a monolithic indexing pipeline written in C++ with a more flexible system of microservices, the majority of them written in Go, that help support Google Search.</li><li><b>Google Chrome:</b> Mobile users of Google Chrome in lite mode rely on the <a href="https://go.dev/solutions/google/chrome" target="_blank">Chrome</a> Optimization Guide server to deliver hints for optimizing page loads of well-known sites in their geographic area. That server, written in Go, helps deliver faster page loads and lowered data usage to millions of users daily.</li><li><b>Firebase:</b> Google Cloud customers turn to <a href="https://go.dev/solutions/google/firebase" target="_blank">Firebase</a> as their mobile and web hosting platform of choice. After joining Google, the team completely migrated its backend servers from Node.js to Go, for the easy concurrency and efficient execution.</li></ul>We hope these stories provide the Go developer community with deeper insight into the reasons why teams at Google choose Go, what they use Go for, and the different paths teams took to those decisions.<br /><br />If you&#8217;d like to share your own story about how your team or organization uses Go, please <a href="https://forms.gle/cNTYFvDQaGCPxMpj9" target="_blank">contact us</a>.<br /><div><br /></div><div><i>By Rob Pike, Distinguished Engineer</i></div></div> <div style='clear: both;'></div> </div> </div> </div> <div class='post-footer'> </div> <div class='post-outer'> <div class='post hentry uncustomized-post-template' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjx0yBGD3blbzrbLyNgitox4PtOFUo-uGlDsUTUWEs8ppBxOXW2sDL6ARuYJkJjSbtK3vT_ONfGeS1kXZJcou9YDFF2DjrWy3bqx2KiMlZrYxRN3iNnHpw7XJYwGFUvWyDjZnBlcMjruS0/s16000/Screen+Shot+2020-08-26+at+5.06.11+PM.png' itemprop='image_url'/> <meta content='8698702854482141883' itemprop='blogId'/> <meta content='1587287596754747122' itemprop='postId'/> <a name='1587287596754747122'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='https://opensource.googleblog.com/2020/08/recapping-major-improvements-in-go-115.html'>Recapping major improvements in Go 1.15 and bringing the Go community together</a> </h3> <div class='post-header'> </div> <div class='post-body entry-content' id='post-body-1587287596754747122' itemprop='description articleBody'> <h2 style="text-align: left;">The Latest Version of Go is Released<br /></h2>In August, the Go team <a href="https://blog.golang.org/go1.15" target="_blank">released Go 1.15</a>, marking another milestone of continuous improvements to the language. As always, many of the updates were supported by our community of contributors in collaboration with the engineering team here at Google.<br /><br />Following our earlier release in February, the latest Go build brings a slew of performance improvements. We&#8217;ve made significant changes behind the scenes to the compiler, reducing binary sizes by about 5%, and improving building Go applications to be around 20% faster and requiring 30% less memory on average. <br /><br />Go 1.15 also includes several updates to the core library, a few security improvements, and much more&#8211;you can dive into the full release notes <a href="https://tip.golang.org/doc/go1.15" target="_blank">here</a>. We&#8217;re really excited to see how developers like you, ranging from those working on indie projects all the way to enterprise devs, will incorporate these updates into your projects. <br /><br />A few users have been working with the release candidates ahead of the latest build and were kind enough to share their experience. <br /><br />Wayne Ashley Berry, a Senior Engineer at <a href="https://www.madewithover.com/" target="_blank">Over</a>, shared that &#8220;...seeing significant performance improvements in the new releases is incredible!&#8221; and, speaking of compiler improvements, <a href="https://twitter.com/waynethebrain/status/1291346686229524480" target="_blank">showed</a> &#8220;one of [their] services compiling ~1.3x faster&#8221; after upgrading to Go 1.15.<br /><br />This mirrored our experience within Google, compiling larger Go applications like <a href="https://kubernetes.io/" target="_blank">Kubernetes</a> which experienced 30% memory reductions and 20% faster builds. <br /><br />These are just a couple examples of how some users have already seen the benefits of Go 1.15. We&#8217;re looking forward to what the rest of the gopher community will do with it!<br /><h2 style="text-align: left;">A Better Experience For Go Developers</h2>Over the last few months we&#8217;ve also been hard at work improving a few things in the Go ecosystem. In July, the VS Code extension for Go officially <a href="https://golang.blog/the-vs-code-go-extension-joins-the-go-project" target="_blank">joined the Go project</a> and more recently, we rolled out a few updates for our online resources.<br /><br />We brought a few important changes to <a href="http://pkg.go.dev/" target="_blank">pkg.go.dev</a>, a central source of information for Go packages and modules. With these changes came functional improvements to make the browsing experience better and minor tweaks across the site (including a <a href="https://pkg.go.dev/" target="_blank">cute new gopher</a>). We also made some changes to <a href="https://go.dev/" target="_blank">go.dev</a>&#8212;our hub for Go developers&#8212;making it easier to navigate the site and find examples of Go&#8217;s use in the enterprise. <br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><img border="0" data-original-height="806" data-original-width="1360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjx0yBGD3blbzrbLyNgitox4PtOFUo-uGlDsUTUWEs8ppBxOXW2sDL6ARuYJkJjSbtK3vT_ONfGeS1kXZJcou9YDFF2DjrWy3bqx2KiMlZrYxRN3iNnHpw7XJYwGFUvWyDjZnBlcMjruS0/s16000/Screen+Shot+2020-08-26+at+5.06.11+PM.png" style="margin-left: auto; margin-right: auto;" /></td></tr><tr><td class="tr-caption" style="text-align: center;">The new home page on pkg.go.dev. Credit to Renee French for the gopher illustration.</td></tr></tbody></table><div>We&#8217;ll be bringing even more improvements to the Go ecosystem in the coming months, so stay tuned!<br /><h2 style="text-align: left;">Our Commitment to Open Source and Google Open Source Live</h2>Most of these changes wouldn&#8217;t be possible without contribution from our open source community through submitting CLs to our release process, organizing community meetups, and engaging in discussions about future changes (like generics).<br /><br />Being part of the open source community is something that the Go team embraces, and Google as a whole works to support every year. It&#8217;s through this community that we&#8217;re able to iterate on our work with a constant feedback loop and bring new gophers into the Go ecosystem. We&#8217;re lucky to have the support of passionate Go advocates, and even get to celebrate the occasional community gopher design!<br /><br />That being said, this has been a challenging year to gather in person for meetups or larger conferences. However, the gopher community has been incredibly resilient, with many meetups taking place virtually, several of which Go team members have been able to attend. <br /><br />We&#8217;d like to help the entire open source community stay connected. In that vein, we&#8217;re excited to announce that Google will host a series of free virtual events, <a href="https://opensourcelive.withgoogle.com/" target="_blank">Google Open Source Live</a>, every month through next year! As part of the series, on November 7th, members of the Go team will be sharing community updates, some things we&#8217;ve been up to, and a few best practices around getting started with Go. <br /><br />Visit the official site for the <a href="https://opensourcelive.withgoogle.com/events/go" target="_blank">Go Day on Google Open Source Live</a>, to learn more about registration and speakers. To keep up-to-date with the Go team, make sure to follow the official <a href="https://twitter.com/golang" target="_blank">Go twitter</a> and visit <a href="https://go.dev/" target="_blank">go.dev</a>, our hub for Go developers. <br /></div><div><br /></div><div><i>By Steve Francia &#8211; Product Lead, Go Team</i></div> <div style='clear: both;'></div> </div> </div> </div> <div class='post-footer'> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry uncustomized-post-template' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTwJVVhMztU017PBXCAaJSpHVr7a8dNj04j3eBWVJtKSQsWiNQThFG6CnwqINUbnKkei5wsMGwj4PTTyZ5DY6lG8U_2-rrhf-fNjRdF_XKBc20iihIJZkTgj55t0CvHdsVBKHMkYxMnn4/s640/OSL-Logo_1200.png' itemprop='image_url'/> <meta content='8698702854482141883' itemprop='blogId'/> <meta content='6184066697490085901' itemprop='postId'/> <a name='6184066697490085901'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='https://opensource.googleblog.com/2020/08/google-open-source-live-monthly.html'>Google Open Source Live: A monthly connection for open source communities</a> </h3> <div class='post-header'> <h4 class='date-header'><span>Tuesday, August 25, 2020</span></h4> </div> <div class='post-body entry-content' id='post-body-6184066697490085901' itemprop='description articleBody'> Starting in September, open source experts at Google will have a new place to meet with you online: <a href="https://opensourcelive.withgoogle.com/" target="_blank">Google Open Source Live</a>, a virtual event series to connect with open source communities with a focus on different technologies and areas of expertise. Google Open Source Live launches on September 3, 2020, and will provide monthly content for open source developers at all levels, contributors, and community members.&nbsp;<div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTwJVVhMztU017PBXCAaJSpHVr7a8dNj04j3eBWVJtKSQsWiNQThFG6CnwqINUbnKkei5wsMGwj4PTTyZ5DY6lG8U_2-rrhf-fNjRdF_XKBc20iihIJZkTgj55t0CvHdsVBKHMkYxMnn4/s1200/OSL-Logo_1200.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="199" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTwJVVhMztU017PBXCAaJSpHVr7a8dNj04j3eBWVJtKSQsWiNQThFG6CnwqINUbnKkei5wsMGwj4PTTyZ5DY6lG8U_2-rrhf-fNjRdF_XKBc20iihIJZkTgj55t0CvHdsVBKHMkYxMnn4/s640/OSL-Logo_1200.png" width="640" /></a></div>The inaugural event of this series will be: The new open source: Leadership, contributions and sustainability, in which the Google Open Source Programs Office, together with Developer Relations specialists, will share an overview of the best ways to get involved and succeed in the open source ecosystem with four exciting sessions. <br /><br />Given how the 2020 pandemic has affected the communities&#8217;s ability to stay engaged and connect, it is important to us to stay present in the ecosystem. Therefore, we made a conscious decision to build an event series for developers to have the opportunity to hear directly from the Google Open Source Programs Office, developer advocates and experts. Each day will provide impactful information in a 2-hour time frame. <br /><h2 style="text-align: left;">Attendee Experience</h2>After attending several virtual events throughout the Summer, we designed our platform with one idea in mind: to create an alternative platform for developers to gather, learn, and interact with experts, and have fun. <br /><br />Attendees can interact with the experts and speakers with Live Q&amp;A chat during the sessions, and join an after party following the event! It&#8217;ll provide a great interactive opportunity for activities and to connect with others. <br /><h2 style="text-align: left;">Sept. 3 Agenda</h2>&#8220;The New Open Source: Leadership, contributions and sustainability&#8221; <br />9 AM - 11 AM PST <br /><span id="docs-internal-guid-c2b35764-7fff-469a-6911-3066ef3ed0af"><br /><div align="left" dir="ltr" style="margin-left: 0pt;"><table style="border-collapse: collapse; border: none;"><colgroup><col width="76"></col><col width="254"></col><col width="294"></col></colgroup><tbody><tr style="height: 0pt;"><td style="background-color: yellow; border-color: rgb(0, 0, 0); border-style: solid; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span style="background-color: transparent; font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Session</span></p></td><td style="background-color: yellow; border-color: rgb(0, 0, 0); border-style: solid; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span style="background-color: transparent; font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Topic&nbsp;</span></p></td><td style="background-color: yellow; border-color: rgb(0, 0, 0); border-style: solid; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span style="background-color: transparent; font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Speaker</span></p></td></tr><tr style="height: 21pt;"><td colspan="3" style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Hosted by</span><span face="" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Stephen Fluin, DevRel Lead and Dustin Ingram, Developer Advocate.&nbsp;&nbsp;</span></p></td></tr><tr style="height: 0pt;"><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">1</span></p></td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">"Be the leader you want in OSS"</span></p></td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Megan Byrd-Sanicki</span></p><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Manager, Operations &amp; Research</span></p></td></tr><tr style="height: 0pt;"><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">2</span></p></td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">"5 simple things you can do to improve OSS docs"</span></p></td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Erin McKean, Docs Advocacy Program Manager, OSPO</span></p></td></tr><tr style="height: 0pt;"><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">3</span></p></td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Fireside Chat: "Business models and contributor engagement in OS"</span></p></td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Seth Vargo, Developer Advocate</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Kaslin Fields, Developer Advocate</span></p></td></tr><tr style="height: 0pt;"><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">4</span></p></td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">"Sustainability in OS"</span></p></td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Megan Byrd-Sanicki, Manager</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">&nbsp;Operations &amp; Research</span></p></td></tr></tbody></table></div></span><h2 style="text-align: left;">Google Open Source Live Event Calendar</h2>Each month will focus on one open source project or concept and feature several speakers who are subject matter experts in their fields. Events take place monthly on the first Thursday.<div><span id="docs-internal-guid-c8f5705b-7fff-4dab-091a-3a919070c7eb"><p dir="ltr" style="background-color: white; line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt;">&nbsp;</p><div align="left" dir="ltr" style="margin-left: 0pt;"><table style="border-collapse: collapse; border: none;"><colgroup><col width="149"></col><col width="149"></col><col width="149"></col><col width="149"></col></colgroup><tbody><tr style="height: 24pt;"><td colspan="4" style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">2020</span></p></td></tr><tr style="height: 21pt;"><td style="background-color: #34a853; border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="background-color: transparent; color: white; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Sep 3</span></p></td><td style="background-color: #34a853; border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="background-color: transparent; color: white; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Oct 1</span></p></td><td style="background-color: #34a853; border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="background-color: transparent; color: white; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Nov 5</span></p></td><td style="background-color: #34a853; border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="background-color: transparent; color: white; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Dec 3</span></p></td></tr><tr style="height: 51.75pt;"><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><a href="https://opensourcelive.withgoogle.com/events/new-open-source" style="text-decoration-line: none;" target="_blank"><span face="" style="color: #1155cc; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; text-decoration-line: underline; text-decoration-skip-ink: none; vertical-align: baseline; white-space: pre-wrap;">The new open source:</span></a></p><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 7pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Leadership, contributions and sustainability</span></p></td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><a href="https://opensourcelive.withgoogle.com/events/knative" style="text-decoration-line: none;" target="_blank"><span face="" style="color: #1155cc; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; text-decoration-line: underline; text-decoration-skip-ink: none; vertical-align: baseline; white-space: pre-wrap;">Knative day</span></a></p><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 7pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">On Google Open Source Live</span></p></td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><a href="https://opensourcelive.withgoogle.com/events/go" style="text-decoration-line: none;" target="_blank"><span face="" style="color: #1155cc; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; text-decoration-line: underline; text-decoration-skip-ink: none; vertical-align: baseline; white-space: pre-wrap;">Go day</span></a></p><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 7pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">On Google Open Source Live</span></p><br /></td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Kubernetes day</span></p><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 7pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">On Google Open Source Live</span></p><br /></td></tr></tbody></table></div><br /><div align="left" dir="ltr" style="margin-left: 0pt;"><table style="border-collapse: collapse; border: none;"><colgroup><col width="149"></col><col width="149"></col><col width="149"></col><col width="149"></col></colgroup><tbody><tr style="height: 24pt;"><td colspan="4" style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">2021</span></p></td></tr><tr style="height: 21pt;"><td style="background-color: #fbbc05; border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="background-color: transparent; color: white; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Feb 4</span></p></td><td style="background-color: #fbbc05; border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="background-color: transparent; color: white; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Mar 4</span></p></td><td style="background-color: #fbbc05; border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="background-color: transparent; color: white; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Apr 1</span></p></td><td style="background-color: #fbbc05; border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="background-color: transparent; color: white; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">May 6</span></p></td></tr><tr style="height: 29.25pt;"><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Istio day</span></p><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 7pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">On Google Open Source Live</span></p></td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Bazel day</span></p><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 7pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">On Google Open Source Live</span></p></td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Beam day</span></p><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 7pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">On Google Open Source Live</span></p></td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Spark day</span></p><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 7pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">On Google Open Source Live</span></p></td></tr></tbody></table></div><div align="left" dir="ltr" style="margin-left: 0pt;"><table style="border-collapse: collapse; border: none;"><colgroup><col width="149"></col><col width="149"></col><col width="149"></col><col width="149"></col></colgroup><tbody><tr style="height: 21pt;"><td style="background-color: #ea4335; border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="background-color: transparent; color: white; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Jun 3</span></p></td><td style="background-color: #ea4335; border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="background-color: transparent; color: white; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Jul 1</span></p></td><td style="background-color: #ea4335; border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="background-color: transparent; color: white; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Aug 5</span></p></td><td style="background-color: #ea4335; border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="background-color: transparent; color: white; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Sep 2</span></p></td></tr><tr style="height: 46.5pt;"><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">CDAP day</span></p><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 7pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">On Google Open Source Live</span></p></td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">Airflow day</span></p><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 7pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">On Google Open Source Live</span></p></td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">OSS Security day</span></p><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 7pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">On Google Open Source Live</span></p></td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99609pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.44; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="" style="color: #222222; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">TBD</span></p><br /></td></tr></tbody></table></div></span><br /><h2 style="text-align: left;">Find out more&nbsp;</h2></div><div><a href="https://opensourcelive.withgoogle.com/" target="_blank">Sign up</a> to receive more details and alerts, and follow <a href="https://twitter.com/GoogleOSS" target="_blank">GoogleOSS@</a> and #GoogleOSlive for updates on Twitter. </div></div><div><br /></div><div><br /></div><i>By Jamie Rachel, Event Program Manager for the Google Open Source Programs Office</i> <div style='clear: both;'></div> </div> </div> </div> <div class='post-footer'> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry uncustomized-post-template' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='https://lh3.googleusercontent.com/Zncl_jdDD84hBZjvVEWfJYGvWtj62Yws1WmErddQw7XOh-0z-DIGGcGPZLBrMoTVs6M9roXeYtL1wfgfR5-hFmK0mTqC-70vb945TzrLC5qzifd79w__N5vYFpUbqS492b06-kzDLw=d' itemprop='image_url'/> <meta content='8698702854482141883' itemprop='blogId'/> <meta content='5329596872071667989' itemprop='postId'/> <a name='5329596872071667989'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='https://opensource.googleblog.com/2020/08/assess-security-of-cloud-deployments.html'>Assess the security of Cloud deployments with InSpec for GCP</a> </h3> <div class='post-header'> <h4 class='date-header'><span>Thursday, August 20, 2020</span></h4> </div> <div class='post-body entry-content' id='post-body-5329596872071667989' itemprop='description articleBody'> <a href="https://github.com/inspec/inspec-gcp" target="_blank">InSpec-GCP version 1.0</a> is now generally available, and two new Chef InSpec&#8482; profiles have been released under an open source software license. The InSpec profiles contain controls for the <a href="https://github.com/GoogleCloudPlatform/inspec-gcp-cis-benchmark" target="_blank">GCP Center for Internet Security (CIS) Benchmark version 1.1.0</a> and the <a href="https://github.com/GoogleCloudPlatform/inspec-gcp-pci-profile" target="_blank">Payment Card Industry Data Security Standard (PCI DSS) version 3.2.1</a>.<br /><h2 style="text-align: left;">The Cloud Security Challenge</h2>Developers are embracing automated continuous integration and continuous delivery (CI/CD), committing many application and infrastructure changes frequently. But centralized security teams can't review every application and infrastructure change. Those teams might have to block deployments (which decreases velocity and undermines continuous delivery) or review changes in production, where misconfigurations are more harmful and changes are more expensive.<br /><br />Security reviews need to "shift left,&#8221; earlier in the software development lifecycle. Security teams likewise need to shift their own efforts to defining policies and providing tools to automate how compliance is verified. When developers adopt these tools, security and compliance checks become part of CI/CD, in a similar fashion to unit, functional, and integration tests, and thus become a normal part of the development workflow. Empowering developers to participate in this process means organizations can achieve continuous compliance. This also reinforces the mindset that <b>security is everyone's responsibility.<br /></b><h2 style="text-align: left;">What is InSpec</h2><a href="https://github.com/inspec/inspec" target="_blank">InSpec</a> is a popular DevSecOps framework that checks the configuration state of resources in virtual machines and containers, on cloud providers such as GCP, AWS, and Azure. InSpec's lightweight nature, approachable domain-specific language, and extensibility make it a valuable tool for:<br /><ul style="text-align: left;"><li>Expressing compliance policies as code</li><li>Enabling development teams to add tests that assess their applications' compliance with security policies before pushing changes to build and release pipelines</li><li>Automating compliance verification in CI/CD pipelines and as part of the release process</li><li>Unifying compliance assessments across multiple cloud providers and on-premises environments</li></ul><h2 style="text-align: left;">InSpec for GCP and compliance profiles</h2>The <a href="https://github.com/inspec/inspec-gcp" target="_blank">InSpec GCP resource pack 1.0</a> provides a consistent way to audit GCP resources. This release unifies the user experience by adding consistent behavior between resources and documentation for available fields. This resource pack also adds support for GCP endpoints that let you audit fields that are in beta (for example, GKE cluster pod security policy configuration).<br /><br />You can use the GCP CIS Benchmark and the PCI DSS InSpec profiles to assess compliance with CIS and PCI DSS policies. CIS Benchmarks are configuration guides used by governments, businesses, industry, and academia. We strongly recommend configuring the workloads to meet or exceed these standards. PCI DSS is required for all organizations that accept or process credit card payments. The <a href="https://github.com/GoogleCloudPlatform/terraform-pci-starter" target="_blank">Terraform PCI Starter</a>, coupled with the PCI InSpec profile, allows deployment of PCI-compliant environments and verifies their ongoing compliance.<br /><br />This work is released under an open source license and we look forward to your feedback and contributions.<br /><h2 style="text-align: left;">Validating PCI DSS and CIS compliance in infrastructure build pipelines</h2>You can use InSpec to validate infrastructure deployments for compliance with standards such as PCI DSS and CIS. An automated validation process of new builds is important to detect insecure and non-compliant configurations as early as possible while minimizing the impact on developer agility.<br /><br />With <a href="https://cloud.google.com/cloud-build" target="_blank">Cloud Build</a> you can create CI pipelines for infrastructure-as-code deployments. You can run InSpec as an additional build step against resources in the GCP project to detect compliance violations in the target infrastructure. While this method doesn't prevent non-compliant build configurations, it does detect compliance issues, fail the build execution, and log the error in Cloud Logging. Cloud Build publishes build messages to a Cloud Pub/Sub topic, which can trigger a Cloud Function to integrate with appropriate alerting systems in case of a failed build. To prevent non-compliant infrastructure in a production environment, run the pipeline in a staging environment before promoting the content to production.<br /><br /><a href="https://github.com/GoogleCloudPlatform/pci-gke-blueprint/blob/master/cicd/cloudbuild.yml" target="_blank">Here</a>&nbsp;is an example pipeline definition for Cloud Build, using InSpec, to validate a project against the PCI guidelines. To run the PCI profile from a container inside a Cloud Build pipeline, clone the Git repository <a href="https://github.com/GoogleCloudPlatform/inspec-gcp-pci-profile" target="_blank">Payment Card Industry Data Security Standard (PCI DSS) version 3.2.1</a>, build the Docker container from the root directory of the repository using the <a href="https://github.com/KonradSchieban/inspec-gcp-pci-profile/blob/feature/docker/Dockerfile" target="_blank">Dockerfile</a>, and push the image to the Google Container Registry. The Cloud Build pipeline will store InSpec reports in a predefined bucket in json and html formats.<br /><br />Here's an example for executing the PCI DSS InSpec profile as a step in a Cloud Build pipeline:<br /><br /><span style="font-family: courier;">#...Previous execution steps<br />#<br />- id: 'Run PCI Profile on in-scope project'<br /> <span>&nbsp;&nbsp;</span>waitFor: ['Write InSpec input file']<br /> <span>&nbsp;&nbsp;</span>name: gcr.io/${_GCR_PROJECT_ID}/inspec-gcp-pci-profile:v3.2.1-3<br /> <span>&nbsp;&nbsp;</span>entrypoint: '/bin/sh'<br /> <span>&nbsp;&nbsp;</span>args: <br /> <span>&nbsp;&nbsp; &nbsp;</span>- '-c'<br /> <span>&nbsp;&nbsp; &nbsp;</span>- |<br /> <span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp;</span>inspec exec /share/. -t gcp:// \<br /> <span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp;</span>--input-file /workspace/inputs.yml \<br /> <span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp;</span>--reporter cli json:/workspace/pci_report.json \<br /> <span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp;</span>html:/workspace/pci_report.html | tee out.json</span><br /><br />Note that in this example a previous execution step writes all required input parameters into the file /workspace/inputs.yml to make them available to the InSpec run. A <a href="https://github.com/GoogleCloudPlatform/pci-gke-blueprint/blob/master/cicd/cloudbuild.yml" target="_blank">CI/CD pipeline</a> has been implemented for the <a href="https://github.com/GoogleCloudPlatform/pci-gke-blueprint" target="_blank">PCI-GKE-Blueprint</a>&nbsp;using Cloud Build and can be referenced as an example.<br /><h2 style="text-align: left;">Try it yourself</h2>Ready to try InSpec? Use this Cloud Shell Walkthrough to quickly install InSpec in your Cloud Shell instance and scan infrastructure in your GCP projects against the CIS Benchmark:<div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://ssh.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2FGoogleCloudPlatform%2Finspec-gcp-cis-benchmark&amp;cloudshell_tutorial=walkthrough.md" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img src="https://lh3.googleusercontent.com/Zncl_jdDD84hBZjvVEWfJYGvWtj62Yws1WmErddQw7XOh-0z-DIGGcGPZLBrMoTVs6M9roXeYtL1wfgfR5-hFmK0mTqC-70vb945TzrLC5qzifd79w__N5vYFpUbqS492b06-kzDLw=d" /></a></div><div><br />Chances are that in the walkthrough the InSpec scan detected some misconfigurations in your project. <br /><br />As a developer of the project, you now know how to quickly scan your deployments, and you can begin to learn more about configuring your resources securely. Our <a href="https://cloud.google.com/foundation-toolkit/" target="_blank">Cloud Foundation Toolkit</a> provides Terraform and Deployment Manager templates for best-practice configurations of your projects and underlying resources. <br /><br />Most large organizations have platform teams that can adopt our Cloud Foundation Toolkit templates, which automate well-configured resource provisioning, and make those available to their developers. These organizations can also include InSpec testing steps in their CI/CD pipelines to provide early feedback to developers and to prevent misconfigured resources from getting released to Production.<br /></div></div><div><br /></div><div><i>By Bakh Inamov &#8211; Security and Compliance Specialist Engineer, Sam Levenick &#8211; Software Engineer, and Konrad Schieban &#8211; Infrastructure Cloud Consultant</i></div> <div style='clear: both;'></div> </div> </div> </div> <div class='post-footer'> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry uncustomized-post-template' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='8698702854482141883' itemprop='blogId'/> <meta content='8386497352153902828' itemprop='postId'/> <a name='8386497352153902828'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='https://opensource.googleblog.com/2020/08/cloud-spanner-emulator-reaches-10.html'>Cloud Spanner Emulator Reaches 1.0 Milestone!</a> </h3> <div class='post-header'> <h4 class='date-header'><span>Wednesday, August 19, 2020</span></h4> </div> <div class='post-body entry-content' id='post-body-8386497352153902828' itemprop='description articleBody'> The <a href="https://cloud.google.com/spanner/docs/emulator" target="_blank">Cloud Spanner emulator</a> provides application developers with the full set of APIs, including the full breadth of SQL and DDL features that can be run locally for prototyping, development and testing. This offline emulator is free and improves developer productivity for customers. Today, we are happy to announce that Cloud Spanner emulator is generally available (GA) with support for Partitioned APIs, Cloud Spanner client libraries, and SQL features.<br /><br />Since <a href="https://medium.com/google-cloud/cloud-spanner-emulator-bf12d141c12" target="_blank">Cloud Spanner emulator&#8217;s beta launch</a> in April, 2020, we have seen strong adoption of the local emulator from customers of Cloud Spanner. Several new and existing customers adopted the emulator in their development &amp; continuous test pipelines. They noticed significant improvements in developer productivity, speed of test execution, and error-free applications deployed to production. We also added several features in this release based on the valuable feedback we received from beta users. The full list of features is documented in the <a href="https://github.com/GoogleCloudPlatform/cloud-spanner-emulator#features-and-limitations" target="_blank">GitHub readme</a>.<br /><h2 style="text-align: left;">Partition APIs</h2>When reading or querying large amounts of data from Cloud Spanner, it can be useful to divide the query into smaller pieces, or partitions, and use multiple machines to fetch the partitions in parallel. The emulator now supports Partition Read, Partition Query, and Partition DML APIs.<br /><h2 style="text-align: left;">Cloud Spanner client libraries</h2>With the GA launch, the latest versions of all the Cloud Spanner client libraries support the emulator. We have added support for C#, Node.js, PHP, Python, Ruby client libraries and the Cloud Spanner JDBC driver. This is in addition to C++, Go and Java client libraries that were already supported with the beta launch. Be sure to check out the <a href="https://github.com/GoogleCloudPlatform/cloud-spanner-emulator#which-client-library-versions-are-supported" target="_blank">minimum version for each of the client libraries</a> that support the emulator.<br /><br />Use the <a href="https://cloud.google.com/spanner/docs/tutorials" target="_blank">Getting Started</a> guides to try the emulator with the client library of your choice.<br /><h2 style="text-align: left;">SQL features</h2>Emulator now supports the full set of SQL features provided by Cloud Spanner. Some of the notable additions being support for SQL functions JSON_VALUE, JSON_QUERY, CEILING, POWER, CHARACTER_LENGTH, and FORMAT. We now also support untyped parameter bindings in SQL statements which are used by our client libraries written in languages with dynamic typing e.g., Python, PHP, Node.js and Ruby.<div><h2 style="text-align: left;">Using Emulator in CI/CD pipelines</h2>You may now point the majority of your existing CI/CD to the Cloud Spanner emulator instead of a real Cloud Spanner instance brought up on GCP. This will save you both cost and time, since an emulator instance comes up instantly and is free to use!<br /><br />What&#8217;s even better is that you can bring up multiple instances in a single execution of the emulator, and of course multiple databases. Thus, tests that interact with a Cloud Spanner database can now run in parallel since each of them can have their own database, making tests hermetic. This can reduce flakiness in unit tests and reduce the number of bugs that can make their way to continuous integration tests or to production.<br /><br />In case your existing CI/CD architecture assumes the existence of a Cloud Spanner test instance and/or test database against which the tests run, you can achieve similar functionality with the emulator as well. Note that the emulator doesn&#8217;t come up with a default instance or a default database as we expect users to create instances and databases as required in their tests for hermeticity as explained above. Below are two examples of how you can bring up an emulator with a default instance or database: 1) By using a docker image or 2) Programmatically.<br /><h3 style="text-align: left;">Starting Emulator from Docker</h3>The emulator can be started using Docker on Linux, MacOS, and Windows. As a prerequisite, you would need to install Docker on your system. To bring up an emulator with a default database/instance, you can execute a shell script in your docker file to do so. Such a script would make RPC calls to CreateInstance and CreateDatabase after bringing up the emulator server. You can also look at <a href="https://github.com/cloudspannerecosystem/emulator-samples/tree/master/docker" target="_blank">this example</a> on how to put this together when using docker. <br /><h3 style="text-align: left;">Run Emulator Programmatically</h3>You can bring up the emulator binary in the same process as your test program. Then you can then create a default instance/database in your &#8216;Setup&#8217; and clean up the same when the tests are over. Note that the exact procedure for bringing up an &#8216;in-process&#8217; service may vary with the client library language and platform of your choice.<br /><br />Other alternatives to start the emulator, including pre-built linux binaries, are listed <a href="https://github.com/GoogleCloudPlatform/cloud-spanner-emulator/blob/master/README.md#quickstart" target="_blank">here</a>.<br />Try it now<br /><br />Learn more about Google Cloud Spanner emulator and try it out <a href="https://cloud.google.com/spanner/docs/emulator" target="_blank">now</a>.<br /><br /><i>By Asheesh Agrawal, Google Open Source</i><br /></div> <div style='clear: both;'></div> </div> </div> </div> <div class='post-footer'> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry uncustomized-post-template' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='8698702854482141883' itemprop='blogId'/> <meta content='8425457692600960460' itemprop='postId'/> <a name='8425457692600960460'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='https://opensource.googleblog.com/2020/08/defcon-differential-privacy-training.html'>DEFCON Differential Privacy Training Launch</a> </h3> <div class='post-header'> <h4 class='date-header'><span>Tuesday, August 18, 2020</span></h4> </div> <div class='post-body entry-content' id='post-body-8425457692600960460' itemprop='description articleBody'> <a href="https://arxiv.org/abs/1909.01917" target="_blank">Differential privacy</a> is a technique that enables organizations to learn from the majority of their data while simultaneously ensuring those results do not allow an individual&#8217;s data to be distinguished or re-identified. A popular way of attaining differential privacy is by adding noise to the data, which provides mathematical bounds on the amount of information that is leaked. Our open source offering aims to help developers implement differential privacy. <br /><br />In the summer of 2019, we publicly launched our <a href="https://github.com/google/differential-privacy" target="_blank">Differential Privacy Library</a>. Since then, we&#8217;ve expanded it from just C++ to also include Go and Java.<br /><br />We&#8217;ve come to realize that differential privacy requires more than just the library to be effectively implemented. We mentioned in a <a href="https://opensource.googleblog.com/2020/06/expanding-our-differential-privacy.html" target="_blank">post</a> earlier this summer that we want all developers to be able to interact with differential privacy, which requires more than an open-sourced library, but rather a training on the topic to share knowledge with all developers. <br /><br />Our goal with this training is to provide a head start that is helpful for those considering differential privacy implementation. We also want to provide an experience on privacy and security that is understood and impactful to any individual in the field, whether they are a beginner or someone who has background knowledge in privacy. <br /><br />This new training contains several steps and covers many topics, such as:<br /><ul style="text-align: left;"><li>The foundations of differential privacy</li><li>Explanations as to why aggregation by itself may not hedge against privacy risks</li><li>The mathematical behind-the-scenes of noise</li><li>Tools that can be used in conjunction with differential privacy</li><li>Codelabs that users can take (in Go)</li><li>Additional resources to address any further questions</li></ul><h2 style="text-align: left;">Step 1: Take our <a href="https://bit.ly/3a76s1N">survey</a>! It only takes five minutes! </h2>This survey enables us to gain insights into what you are expecting to gain from this training. We are curious about what your objectives and goals are with this training, and if you have any experience with differential privacy.<br /><h2 style="text-align: left;">Step 2: Check-out an<a href="https://bit.ly/30A3JLl"> introductory video</a> to Differential Privacy! </h2>We introduce topics like data aggregation, k-anonymity, differential privacy, noise, and others. The goal of this module is to introduce the foundations behind the differential privacy, and why it is an important and useful privacy tool. <br /><h2 style="text-align: left;">Step 3: Try-out our<a href="https://bit.ly/3a4EWCk"> codelabs</a> </h2>We have provided Codelabs in Go to help you practice implementing Differential Privacy library end-to-end.<br /><h2 style="text-align: left;">Step 4: Learn more about <a href="https://bit.ly/2F09RnJ">differential privacy</a>.</h2>We want to offer an additional resource to help answer any questions you may have. If you have other resources that you find, please let us know and we will add these links to our overall training.<br /><h2 style="text-align: left;">Step 5: Provide us with some <a href="https://bit.ly/3gFzR5K">feedback</a></h2>Please use this survey as a platform to share your experience with this pilot. Did the content meet your expectations? Did it make sense? What was missing? This is the time for you to share your point of view and any pain points you experienced (as well as any positive aspects you encountered).<br /><br />We hope this training provides an impactful experience from beginner coders to privacy specialists. The public differential privacy training will launch at the Stanford Biodesign: &#8220;<a href="https://biodesign.stanford.edu/news---events/virtual-buildathon.html" target="_blank">Building for Digital Health&#8221; Buildathon</a>, Sept 11-13, 2020, led by Stanford, and supported by Google Cloud and Apple Health engineers.<br /><br />Please continue to reach out to us to share your experiences with us at <a href="mailto:differential-privacy-feedback@google.com" target="_blank">differential-privacy-feedback@google.com</a>. The suggestions we receive will help us improve and it will inform our thinking as we add new features and updates. <br /><br /><i>Acknowledgements: Miguel Guevara, Bryant Gipson, Royce Wilson, Kate Frankenberg, Katie Holzheimer, Lior Gottleib, Carmen Bush</i><br /><br /><i>By Aditi Joshi &#8211; Security and Privacy Engineering, Google Cloud</i> <div style='clear: both;'></div> </div> </div> </div> <div class='post-footer'> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry uncustomized-post-template' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh88EtYNGu34xREzkQQjq4dapNABQn23rQ0Y-286CNcY0VHIyjq29RntgOV0JKlsywhKHPX0Md7a57toxhP0TEasr-fMZpRu_Gt-FpnoYgmVrYzxfhtz0yue0k7ChO4SUttWiIrJrcKJvQ/w320-h259/SeasonofDocs_Icon_Grey_300ppi.png' itemprop='image_url'/> <meta content='8698702854482141883' itemprop='blogId'/> <meta content='3063377055639830883' itemprop='postId'/> <a name='3063377055639830883'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='https://opensource.googleblog.com/2020/08/season-of-docs-announces-2020-technical.html'>Season of Docs announces 2020 technical writing projects</a> </h3> <div class='post-header'> <h4 class='date-header'><span>Monday, August 17, 2020</span></h4> </div> <div class='post-body entry-content' id='post-body-3063377055639830883' itemprop='description articleBody'> <div class="separator"><div class="separator" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em; text-align: center;"><img border="0" data-original-height="1012" data-original-width="1250" height="259" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh88EtYNGu34xREzkQQjq4dapNABQn23rQ0Y-286CNcY0VHIyjq29RntgOV0JKlsywhKHPX0Md7a57toxhP0TEasr-fMZpRu_Gt-FpnoYgmVrYzxfhtz0yue0k7ChO4SUttWiIrJrcKJvQ/w320-h259/SeasonofDocs_Icon_Grey_300ppi.png" width="320" /></div></div><a href="http://developers.google.com/season-of-docs" target="_blank">Season of Docs</a> has announced the technical writers participating in the program and their projects! You can view a <a href="https://developers.google.com/season-of-docs/docs/participants/" target="_blank">list of organizations and technical writing projects</a> on the website.<br /><br /><div>The program received over 500 technical writer applications, and with them, over 800 technical writing project proposals. The enthusiasm from the technical writing and open source communities has been amazing!<br /><div><h2 style="text-align: left;">What is next?</h2>During the community bonding period from August 17 to September 13, mentors must work with the technical writers to prepare them for the doc development phase. By the end of community bonding, the technical writer should be familiar with the open source project and community, understand the product as a whole, establish communication channels with the mentoring organization, and set clear goals and expectations for the project. These are critical to the successful completion of the technical writing project.</div><div><br />Documentation development begins on <b>September 14, 2020</b>.</div><div><h2 style="text-align: left;">What is Season of Docs?</h2>Documentation is essential to the adoption of open source projects as well as to the success of their communities. Season of Docs brings together technical writers and open source projects to foster collaboration and improve documentation in the open source space. You can find out more about the program on the <a href="https://developers.google.com/season-of-docs/docs/" target="_blank">introduction</a> page of the website.<br /><br />During the program, technical writers spend a few months working closely with an open source community. They bring their technical writing expertise to the project's documentation and, at the same time, learn about the open source project and new technologies.<br /><br />The open source projects work with the technical writers to improve the project's documentation and processes. Together, they may choose to build a new documentation set, redesign the existing docs, or improve and document the project's contribution procedures and onboarding experience.<br /><h2 style="text-align: left;">General timeline <table border=""> <tbody> <tr><td><b>August 16</b></td><td>Google announces the accepted technical writer projects</td></tr> <tr><td><b>August 17 - September 13</b></td><td>Community bonding: Technical writers get to know mentors and the open source community, and refine their projects in collaboration with their mentors</td></tr> <tr><td><b>September 14 - December 5</b></td><td>Technical writers work with open source mentors on the accepted projects, and submit their work at the end of the period</td></tr> <tr><td><b>January 6, 2021</b></td><td>Google publishes the list of successfully-completed projects</td></tr></tbody></table></h2>See the full <a href="https://developers.google.com/season-of-docs/docs/timeline" target="_blank">timeline</a> for details, including the provision for projects that run longer than three months.<br /><h2 style="text-align: left;">Find out more</h2>Explore the Season of Docs website at <a href="https://g.co/seasonofdocs" target="_blank">g.co/seasonofdocs</a> to learn more about the program. Use our logo and other promotional resources to <a href="https://developers.google.com/season-of-docs/docs/press" target="_blank">spread the word</a>. Check out the <a href="https://developers.google.com/season-of-docs/docs/faq" target="_blank">FAQ</a> for further questions!<br /><br /><i>By Kassandra Dhillon and Erin McKean, Program Managers, Google Open Source Programs Office</i><br /></div></div> <div style='clear: both;'></div> </div> </div> </div> <div class='post-footer'> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry uncustomized-post-template' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='https://lh5.googleusercontent.com/QIm6oWPtjmbJDCgVe53ZMEAJSzmiJ2ZF5OpaAoyyTUaXwU5IXXNfSMwaJwk28DeukKX_oOs8vGUmBskaI-MNvCLrtFEZs3R9cwu5_24JaspRiQABf61RXoo4OD90oJYAppAjUZcSfw=w1319-h715' itemprop='image_url'/> <meta content='8698702854482141883' itemprop='blogId'/> <meta content='8781607252306888147' itemprop='postId'/> <a name='8781607252306888147'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='https://opensource.googleblog.com/2020/08/java-zpages-for-opentelemetry.html'>Java zPages for OpenTelemetry</a> </h3> <div class='post-header'> <h4 class='date-header'><span>Friday, August 14, 2020</span></h4> </div> <div class='post-body entry-content' id='post-body-8781607252306888147' itemprop='description articleBody'> <h2 style="text-align: left;">What is OpenTelemetry?</h2><a href="https://opentelemetry.io/" target="_blank">OpenTelemetry</a> is an open source project aimed at improving the observability of our applications. It is a collection of cloud monitoring libraries and services for capturing distributed <a href="https://opentracing.io/docs/overview/what-is-tracing/" target="_blank">traces</a> and <a href="https://opencensus.io/stats/" target="_blank">metrics</a> and integrates naturally with external observability tools, such as Prometheus and Zipkin. As of now, OpenTelemetry is in its beta stage and supports a <a href="https://opentelemetry.io/docs/" target="_blank">few</a> different languages.<br /><h2 style="text-align: left;">What are <span style="font-family: courier;">zPages</span>?</h2><span style="font-family: courier;">zPages</span> are a set of dynamically generated HTML web pages that display trace and metrics data from the running application. The term <span style="font-family: courier;">zPages</span> was coined at Google, where similar pages are used to view basic diagnostic data from a particular host or service. For our project, we built the Java <span style="font-family: courier;">/tracez</span> and <span style="font-family: courier;">/traceconfigz zPages</span>, which focus on collecting and displaying trace spans.<br /><h3 style="text-align: left;"><span style="font-family: courier;">TraceZ</span></h3>The <span style="font-family: courier;">/tracez zPage</span> displays span data from the instrumented application. Spans are split into two groups: spans that are still running and spans that have completed.<br /><h3 style="text-align: left;"><span style="font-family: courier;">TraceConfigZ</span></h3>The <span style="font-family: courier;">/traceconfigz zPage</span> displays the currently active tracing configuration and allows users to change the tracing parameters. Examples of such parameters include the sampling probability and the maximum number of attributes.<br /><h2 style="text-align: left;">Using the <span style="font-family: courier;">zPages</span></h2>This section describes how to start and use the <a href="https://github.com/open-telemetry/opentelemetry-java/tree/master/sdk_extensions/zpages" target="_blank">Java zPages</a>.<br /><h3 style="text-align: left;">Add the dependencies to your project</h3>First, you need to add OpenTelemetry as a dependency to your Java application.<br /><h4 style="text-align: left;">Maven</h4>For Maven, add the following to your <span style="font-family: courier;">pom.xml</span> file:<span id="docs-internal-guid-66e2b7e6-7fff-3454-0018-df2ea305f520"><br /><div align="left" dir="ltr" style="margin-left: 0pt;"><table style="border-collapse: collapse; border: none;"><colgroup><col width="623"></col></colgroup><tbody><tr style="height: 136.5pt;"><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99375pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><span style="font-family: courier;">&lt;dependencies&gt;<br /><span>&nbsp;&nbsp; &nbsp;</span>&lt;dependency&gt;<br /><span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp; &nbsp;</span>&lt;groupId&gt;io.opentelemetry&lt;/groupId&gt;<br /><span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp; &nbsp;</span>&lt;artifactId&gt;opentelemetry-api&lt;/artifactId&gt;<br /><span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp; &nbsp;</span>&lt;version&gt;0.7.0&lt;/version&gt;<br /><span>&nbsp;&nbsp; &nbsp;</span>&lt;/dependency&gt;<br /><span>&nbsp;&nbsp; &nbsp;</span>&lt;dependency&gt;<br /><span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp; &nbsp;</span>&lt;groupId&gt;io.opentelemetry&lt;/groupId&gt;<br /><span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp; &nbsp;</span>&lt;artifactId&gt;opentelemetry-sdk&lt;/artifactId&gt;<br /><span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp; &nbsp;</span>&lt;version&gt;0.7.0&lt;/version&gt;<br /><span>&nbsp;&nbsp; &nbsp;</span>&lt;/dependency&gt;<br /><span>&nbsp;&nbsp; &nbsp;</span>&lt;dependency&gt;<br /><span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp; &nbsp;</span>&lt;groupId&gt;io.opentelemetry&lt;/groupId&gt;<br /><span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp; &nbsp;</span>&lt;artifactId&gt;opentelemetry-sdk-extension-<span>&nbsp;&nbsp; &nbsp;</span>zpages&lt;/artifactId&gt;<br /><span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp; &nbsp;</span>&lt;version&gt;0.7.0&lt;/version&gt;<br /><span>&nbsp;&nbsp; &nbsp;</span>&lt;/dependency&gt;<br />&lt;/dependencies&gt;</span></td></tr></tbody></table></div></span><h4 style="text-align: left;">Gradle</h4>For Gradle, add the following to your <span style="font-family: courier;">build.gradle</span> dependencies:<span id="docs-internal-guid-5a9b6d80-7fff-210d-800a-f2a6a268c778"><br /><div align="left" dir="ltr" style="margin-left: 0pt;"><table style="border-collapse: collapse; border: none;"><colgroup><col width="623"></col></colgroup><tbody><tr style="height: 31.5pt;"><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99375pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><span style="font-family: courier;">implementation 'io.opentelemetry:opentelemetry-api:0.7.0'<br />implementation 'io.opentelemetry:opentelemetry-sdk:0.7.0'<br />implementation 'io.opentelemetry:opentelemetry-sdk-extension-zpages:0.7.0'</span></td></tr></tbody></table></div></span><h3 style="text-align: left;"><span>Register the zPages</span></h3><div>To set-up the <span style="font-family: courier;">zPages</span>, simply call <span style="font-family: courier;">startHttpServerAndRegisterAllPages(int port)</span> from the ZPageServer class in your main function:<span id="docs-internal-guid-51a5bbbc-7fff-0237-80c5-267232cdf207"><br /><div align="left" dir="ltr" style="margin-left: 0pt;"><table style="border-collapse: collapse; border: none;"><colgroup><col width="623"></col></colgroup><tbody><tr style="height: 31.5pt;"><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99375pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><span style="font-family: courier;">import io.opentelemetry.sdk.extensions.zpages.ZPageServer;<br /><br />public class MyMainClass {<br /><span>&nbsp;&nbsp; &nbsp;</span>public static void main(String[] args) throws Exception {<br /><span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp; &nbsp;</span>ZPageServer.startHttpServerAndRegisterAllPages(8080);<br /><span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp; &nbsp;</span>// ... do work<br /><span>&nbsp;&nbsp; &nbsp;</span>}<br />}</span></td></tr></tbody></table></div></span>Note that the package <span style="font-family: courier;">com.sun.net.httpserver</span> is required to use the default zPages setup. Please make sure your version of the JDK includes this package if you plan to use the default server.<br /><br />Alternatively, you can call <span style="font-family: courier;">registerAllPagesToHttpServer(HttpServer server</span>) to register the <span style="font-family: courier;">zPages</span> to a shared server:<span id="docs-internal-guid-b8f992e2-7fff-7c24-b234-2f72101c05c3"><br /><div align="left" dir="ltr" style="margin-left: 0pt;"><table style="border-collapse: collapse; border: none;"><colgroup><col width="623"></col></colgroup><tbody><tr style="height: 31.5pt;"><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 0.99375pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><span style="font-family: courier;">import io.opentelemetry.sdk.extensions.zpages.ZPageServer;<br /><br />public class MyMainClass {<br /> <span>&nbsp;&nbsp; &nbsp;</span>public static void main(String[] args) throws Exception {<br /> <span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp; &nbsp;</span>HttpServer server = HttpServer.create(new <span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp; &nbsp;</span>InetSocketAddress(8000), 10);<br /> <span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp; &nbsp;</span>ZPageServer.registerAllPagesToHttpServer(server);<br /><span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp; &nbsp;</span>server.start();<br /> <span>&nbsp;&nbsp; &nbsp;</span><span>&nbsp;&nbsp; &nbsp;</span>// ... do work<br /> <span>&nbsp;&nbsp; &nbsp;</span>}<br />}</span></td></tr></tbody></table></div></span><h3 style="text-align: left;">Access the zPages</h3><h4 style="text-align: left;">View all available <span style="font-family: courier;">zPages</span> on the index page</h4>The index page (at /) lists all available <span style="font-family: courier;">zPages</span> with a link and description.<br /><br /><span id="docs-internal-guid-cf7789cb-7fff-577e-ef46-dce2e08abb55"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="border: none; display: inline-block; height: 339px; overflow: hidden; width: 624px;"><img height="715" src="https://lh5.googleusercontent.com/QIm6oWPtjmbJDCgVe53ZMEAJSzmiJ2ZF5OpaAoyyTUaXwU5IXXNfSMwaJwk28DeukKX_oOs8vGUmBskaI-MNvCLrtFEZs3R9cwu5_24JaspRiQABf61RXoo4OD90oJYAppAjUZcSfw=w1319-h715" style="margin-left: 0px; margin-top: 0px;" width="1319" /></span></span></span><br /><h4 style="text-align: left;">View trace spans on the <span style="font-family: courier;">/tracez zPage</span></h4>The <span style="font-family: courier;">/tracez zPage</span> displays information about running and completed spans, with completed spans further organized into latency and error buckets. The data is aggregated into a summary-level table:<br /><br /><img src="https://lh4.googleusercontent.com/75E9jS0oUQsUrCaWUpKw_FzGX0CsGh6RsvXoMy-MSOrZuQZsO4TtLcSkGSy_HeTo5guCoFxVAfkR-W5L7JrsK-9dGypUiBzqBA0sEZtW_NDrNo2F2D-zVp7e7BvL1URFFTFjOGf_8w" /><br />You can click on each of the counts in the table cells to access the corresponding span details. For example, here are the details of the ChildSpan latency sample (row 1, col 4):<br /><br /><img src="https://lh3.googleusercontent.com/D-pAzGvXER6ZIY1YerH3W-iKhWunh6uK5ve_Z3KVFBwMBN-DGWmlXL-ZbaaSbmh4ZzBrAAGKqQcS2hzbiLo3S8On0hc92jKyekmioOgQ-x1zwUmrH1StwOmJdwwy0v8hgGuKBuH-Ww" /><br />View and update the tracing configuration on the <span style="font-family: courier;">/traceconfigz zPage.</span><br /><br />The <span style="font-family: courier;">/traceconfigz zPage</span> provides an interface for users to modify the current tracing parameters:<br /><br /><img src="https://lh3.googleusercontent.com/pyXPhXBFNXWygdEItIiAhAZU4-5Xp0OONCBi0azhaD_ijOx_3TYnd5DsBoIe9cdVBeu4jMFFXDMyPr5N1pbxl-hNmcHD9g3h0n9nz7Qlza2UbrMoSXQStR446M0mv7pab9EYJEZQYg" /><img src="https://lh6.googleusercontent.com/nx1tnV89yz4hB7qwLcS8VCej6zzfK4-lWEQZGuM62ILxr7QxN1MN9ndyYjOT_yQU3hVKSRCP9fSfPWD1dT1A9Ty7gqXVSYLnsxWv-K5rHL1YPGLkjcBdYN1tWbksMuhz00mxJPdB9Q" /><br /><h2 style="text-align: left;">Design</h2>This section goes into the underlying design of our code.<br /><h3 style="text-align: left;">Frontend</h3><img src="https://lh6.googleusercontent.com/GdzVWmzGvPH3HNaSoqVaZ_r639OwB_CwEc0USAEk26tJLiCtvU1xW7Vyq0fLAPN5XXGSTF3OjzAe8BAqJwcap8kdXral4j6hRvRoa9E2nIhYbEls7GqpcUtCoEt3ZLKc9xQMI3OSrA" /><br />The frontend consists of two main parts: <span style="font-family: courier;">HttpHandler</span> and <span style="font-family: courier;">HttpServer</span>. The <span style="font-family: courier;">HttpHandler</span> is responsible for rendering the HTML content, with each <span style="font-family: courier;">zPage</span> implementing its own <span style="font-family: courier;">ZPageHandler</span>. The <span style="font-family: courier;">HttpServer</span>, on the other hand, is responsible for listening to incoming requests, obtaining the requested data, and then invoking the aforementioned<span style="font-family: courier;"> ZPageHandlers</span>. The <span style="font-family: courier;">HttpServer</span> class from com.sun.net is used to construct the default server and to handle http requests on different routes.<br /><h3 style="text-align: left;">Backend</h3><br /><img src="https://lh3.googleusercontent.com/NaQ1VUPx8cebqetTxpvIFMmKgeOF-4Rf0STqDT2qMWFNYSwm_1bPc-pcDpC5LKOLTyqa2hyoDp9V_pOzNLd3U5A-EjSAp1o7UqOomVahIbjdvOOolukXGrEESKqdDEOCtVaHPnXFrw" /><br /><br /><br />The backend consists of two components as well: <span style="font-family: courier;">SpanProcessor</span> and <span style="font-family: courier;">DataAggregator.</span> The <span style="font-family: courier;">SpanProcessor</span> watches the lifecycle of each span, invoking functions each time a span starts or ends. The <span style="font-family: courier;">DataAggregator</span>, on the other hand, restructures the data from the <span style="font-family: courier;">SpanProcessor</span> into an accessible format for the frontend to display. The class constructor requires a <span style="font-family: courier;">TracezSpanProcessor </span>instance, so that the <span style="font-family: courier;">TracezDataAggregator</span> class can access the spans collected by a specific <span style="font-family: courier;">TracezSpanProcessor</span>. The frontend only needs to call functions in the <span style="font-family: courier;">DataAggregator</span> to obtain information required for the web page.<br /><h2 style="text-align: left;">Conclusion</h2>We hope that this blog post has given you a little insight into the development and use cases of OpenTelemetry&#8217;s Java <span style="font-family: courier;">zPages</span>. The <span style="font-family: courier;">zPages</span> themselves are lightweight performance monitoring tools that allow users to troubleshoot and better understand their applications. Once OpenTelemetry is officially released, we hope that you try out and use the <span style="font-family: courier;">/tracez</span> and <span style="font-family: courier;">/traceconfigz zPages</span>!<br /><br /><i>By William Hu and Terry Wang &#8211; Software Engineering Interns, Core Compute Observability</i></div> <div style='clear: both;'></div> </div> </div> </div> <div class='post-footer'> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry uncustomized-post-template' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='8698702854482141883' itemprop='blogId'/> <meta content='7366145662344042759' itemprop='postId'/> <a name='7366145662344042759'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='https://opensource.googleblog.com/2020/08/google-summer-of-code-2020-statistics.html'>Google Summer of Code 2020 Statistics: Part 2</a> </h3> <div class='post-header'> <h4 class='date-header'><span>Thursday, August 13, 2020</span></h4> </div> <div class='post-body entry-content' id='post-body-7366145662344042759' itemprop='description articleBody'> With the program nearing the end of the summer, it&#8217;s time for another round of updates!<div><h2 style="text-align: left;">Universities</h2>The 1,198 students accepted into the GSoC 2020 program came from 550 universities, of which, 114 have students participating for the first time in GSoC.<br /><br />Schools with the most accepted students for GSoC 2020: <table border="1|0"> <tbody> <tr><td><b>University</b></td><td><b># of Accepted Students</b></td></tr> <td>Indian Institute of Technology, Roorkee</td><td>48</td></tr> <td>Indian Institute of Technology, Kanpur</td><td>27</td></tr> <td>International Institute of Information Technology, Hyderabad</td><td>24</td></tr> <td>National Institute of Technology Karnataka, Surathkal</td><td>23</td></tr> <td>Birla Institute of Technology and Science, Pilani (BITS Pilani)</td><td>13</td></tr> <td>Indian Institute of Technology, Kharagpur</td><td>13</td></tr> <td>Indian Institute of Technology (BHU), Varanasi</td><td>11</td></tr> <td>University of Moratuwa</td><td>11</td></tr> <td>National Institute of Technology, Hamirpur</td><td>10</td></tr> <td>Amrita Vishwa Vidyapeetham, Amritapuri Campus</td><td>10</td></tr> <td>University of Tokyo</td><td>10</td></tr> <td>University Of Colombo School Of Computing (UCSC)</td><td>10</td></tr> </tbody></table> </div><div><h2 style="text-align: left;">Mentors</h2><div>Each year we pore over gobs of data to extract some interesting statistics about the GSoC mentors. Here&#8217;s a quick synopsis of our 2020 crew:<br /><ul style="text-align: left;"><li>Registered mentors: 3,592</li><li>Mentors with assigned student projects: 2,156</li><li>Mentors who have participated in GSoC for 10 or more years: 78</li><li>Mentors who have been a part of GSoC for 5 years or more: 199</li><li>Mentors that are former GSoC students: 533 (24.7%)</li><li>Mentors that have also been involved in the Google Code-in program: 405 (18.8%)</li><li>Percentage of new mentors: 34.18%</li></ul>GSoC 2020 had an international representation with mentors from 67 countries around the world!<br /><br />The global pandemic, COVID-19, brought additional challenges to this year&#8217;s GSoC program. Whether living with the virus, adjusting to shifting school and work schedules, or pivoting to a remote lifestyle, students and mentors have had to prioritize their safety and delicately balance their new way of life. Despite these unprecedented times, our students continue to push on and our mentors fully support our students by sharing their passion for open source, listening to their concerns and providing them with valuable advice. For that commitment, we would like to acknowledge and give thanks to all students and mentors in the GSoC 2020 program. Not even a pandemic can dampen your enthusiasm and tireless contributions to the open source community!<br /><div><br /></div><div><i>By&nbsp;Stephanie Taylor &#8211; Program Manager, Google Open Source Programs Office</i></div></div></div> <div style='clear: both;'></div> </div> </div> </div> <div class='post-footer'> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry uncustomized-post-template' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='https://upload.wikimedia.org/wikipedia/commons/c/c1/Wikiloop_DoubleCheck_logo.png' itemprop='image_url'/> <meta content='8698702854482141883' itemprop='blogId'/> <meta content='6569768216543567774' itemprop='postId'/> <a name='6569768216543567774'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='https://opensource.googleblog.com/2020/08/supporting-wikipedia-with-more-tools.html'>Supporting Wikipedia with more tools for editors</a> </h3> <div class='post-header'> <h4 class='date-header'><span>Tuesday, August 11, 2020</span></h4> </div> <div class='post-body entry-content' id='post-body-6569768216543567774' itemprop='description articleBody'> Google has a commitment to making information more accessible to people around the world, while ensuring that the information on the web is accurate and reflects the diversity of its users. Just like Google supports open source software development, WikiLoop is one of the explorations on better contributing to the open knowledge movement. To this day, Wikipedia, a Wikimedia movement project, remains a reliable information source that is also available with an open license, which makes it possible for Knowledge Engine of Google&#8212;as well as knowledge graph systems operated by others &#8212;to draw excerpts from it for Search features and other apps. With the project&#8217;s sustainability in mind, Google has contributed back to the Wikimedia movement in <a href="https://www.blog.google/products/search/expanding-knowledge-access-wikimedia-foundation/" target="_blank">a number of ways</a> since 2018. Building on this commitment, Google created the umbrella program WikiLoop in 2019, which hosts several tools for editors that focus on content quality, like <a href="http://doublecheck.wikiloop.org/" target="_blank">WikiLoop DoubleCheck.</a>&nbsp;<div class="separator" style="clear: both; text-align: center;"><a href="https://upload.wikimedia.org/wikipedia/commons/c/c1/Wikiloop_DoubleCheck_logo.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="400" data-original-width="800" height="246" src="https://upload.wikimedia.org/wikipedia/commons/c/c1/Wikiloop_DoubleCheck_logo.png" width="491" /></a></div><div>WikiLoop is led by Zainan Zhou&#8212;a Googler for the last 7 years, and a Wikipedian for the last 5&#8212;who works as a software engineer in the Knowledge Engine team at Google. When he joined the free encyclopedia as an editor, he always wondered how his company could contribute to this open source project. Zainan involved the Wikipedia communities in every step of the development of WikiLoop, connecting with editors from different parts of the world at Wikimedia events, like <a href="https://commons.wikimedia.org/wiki/File:WikiLoop_at_WikiDataCon_2019.pdf" target="_blank">WikidataCon</a>, Wikimania, Wiki Conference North America, and WikiDevSummit, throughout 2019. The most recent involvement with the community of Wikipedia editors included a consultation and <a href="https://meta.wikimedia.org/wiki/WikiLoop/New_name_vote" target="_blank">vote</a> to change the name of the most popular WikiLoop artifact, a tool for peer-review of Wikipedia articles, DoubleCheck.<br /><br />In the past few months, we focused on raising awareness of WikiLoop DoubleCheck. This tool allows registered and unregistered users to mark new edits with tags &#8220;looks good&#8221;, &#8220;not sure&#8221;, and &#8220;should revert&#8221;, a peer review system which editors could use to approve or revert new content on Wikipedia. Since its launch, the tool has witnessed a 309% quarter over quarter growth in tags added, and over 1,000 editors have used it to review Wikipedia content. With the help of volunteer translators and machine translation, WikiLoop DoubleCheck is now made available in 25 <a href="https://github.com/google/wikiloop-doublecheck/tree/master/i18n/locales" target="_blank">languages</a>, and we hope to continue serving more Wikipedia editors in the months to come. In order for Google&#8217;s Knowledge Engine to organize the world's information, the knowledge source needs to be healthy. While peer-review on Wikipedia is an established process that has been going on for years, tools like WikiLoop DoubleCheck support the thousands of volunteers who dedicate their time to this task on Wikipedia by making information verification more accessible.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://upload.wikimedia.org/wikipedia/commons/3/35/Wikiloop-DoubleCheck-Demo-v4.1.0.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="462" data-original-width="573" src="https://upload.wikimedia.org/wikipedia/commons/3/35/Wikiloop-DoubleCheck-Demo-v4.1.0.gif" /></a></div><div><br />The WikiLoop program was originally conceived as a virtuous circle: providing data and tools to enhance human editor's productivity, and making the Wikipedia editorial input more machine-readable for open knowledge institutions, academia and researchers interested in advancing machine learning technology. <br /><br />WikiLoop leverages Google&#8217;s talents at software development to contribute to global Wikipedia content accuracy by enhancing the existing suite of Wikimedia and community tools for content validation at scale.&nbsp;While WikiLoop is a contribution of Google to the Wikipedia communities, Google and the Wikimedia Foundation have partnered in other areas as well.&nbsp;Learn more about Google&#8217;s partnership with the Wikimedia Foundation on the <a href="https://meta.wikimedia.org/wiki/Overview_of_Wikimedia_Foundation_and_Google_Partnership" target="_blank">partnership&#8217;s page on Meta-Wikimedia</a>.&nbsp;<div><br />While probably the most popular in the set, DoubleCheck is not the only tool under the WikiLoop umbrella. We are also building data sets and tools and continue to explore other opportunities to contribute to the open knowledge movement. Learn more about tools and other initiatives, like the Coalition call, on <a href="https://meta.wikimedia.org/wiki/WikiLoop" target="_blank">the program&#8217;s page on Meta-Wikimedia</a>. </div></div><div><br /></div><i>By María Cruz </i>&#8211;<i>&nbsp;Program Manager, Google Open Source Programs Office</i> <div style='clear: both;'></div> </div> </div> </div> <div class='post-footer'> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry uncustomized-post-template' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='8698702854482141883' itemprop='blogId'/> <meta content='5775029535899484230' itemprop='postId'/> <a name='5775029535899484230'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='https://opensource.googleblog.com/2020/08/introducing-tensorflow-recorder.html'>Introducing TensorFlow Recorder</a> </h3> <div class='post-header'> <h4 class='date-header'><span>Friday, August 7, 2020</span></h4> </div> <div class='post-body entry-content' id='post-body-5775029535899484230' itemprop='description articleBody'> When training computer vision machine learning models, data loading can often be a performance bottleneck, causing your GPU or TPU resources to be underutilized while waiting for data to be loaded into the model. Storing your dataset in the efficient <a href="https://www.tensorflow.org/tutorials/load_data/tfrecord" target="_blank">TensorFlow Record (<font face="courier">TFRecord</font>)</a> format is a great way to solve these problems, but creating <font face="courier">TFRecords</font> can unfortunately often require a great deal of complex code.<br /><br />Last week we open sourced the <a href="https://github.com/google/tensorflow-recorder" target="_blank">TensorFlow Recorder</a> project (also known as <font face="courier">TFRecorder</font>), which makes it possible for data scientists, data engineers, or AI/ML engineers to create image based <font face="courier">TFRecords</font> with just a few lines of code. Using <font face="courier">TFRecords</font> is incredibly important for creating efficient TensorFlow ML pipelines, but until now they haven&#8217;t been so easy to create. Before <font face="courier">TFRecorder</font>, in order to create <font face="courier">TFRecords </font>at scale you would have had to write a data pipeline that parsed your structured data, loaded images from storage, and serialized the results into the <font face="courier">TFRecord </font>format. <font face="courier">TFRecorder</font> allows you to write <font face="courier">TFRecords</font> directly from a Pandas dataframe or CSV without writing any complicated code. <br /><br />You can see an example of <font face="courier">TFRecoder&nbsp;</font>below, but first let&#8217;s talk about some of the specific advantages of <font face="courier">TFRecords</font>.<br /><h2 style="text-align: left;">How TFRecords Can Help</h2>Using the <font face="courier">TFRecord </font>file format allows you to store your data in sets of files, each containing a sequence of <a href="https://developers.google.com/protocol-buffers/" target="_blank">protocol buffers</a> serialized as a binary record that can be read very efficiently, which will help reduce the data loading bottleneck mentioned above. <br /><br />Data loading performance can be further improved by implementing <a href="https://www.tensorflow.org/guide/data_performance" target="_blank">prefetching and parallel interleave</a> along with using the <font face="courier">TFRecord </font>format. Prefetching reduces the time of each model training step(s) by fetching the data for the next training step while your model is executing training on the current step. Parallel interleave allows you to read from multiple <font face="courier">TFRecords</font> shards (pieces of a <font face="courier">TFRecord</font> file) and apply preprocessing of those interleaved data streams. This reduces the latency required to read a training batch and is especially helpful when reading data from the network. <br /><h2 style="text-align: left;">Using TensorFlow Recorder</h2>Creating a <font face="courier">TFRecord</font> using <font face="courier">TFRecorder</font> requires only a few lines of code. Here&#8217;s how it works.<div><span id="docs-internal-guid-60715c53-7fff-3ca4-8abe-6681d506f5da"><div align="left" dir="ltr" style="margin-left: 0pt;"><table style="border-collapse: collapse; border: none; table-layout: fixed; width: 468pt;"><colgroup><col></col></colgroup><tbody><tr style="height: 0pt;"><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><font face="courier">import pandas as pd<br />import tfrecorder<br />df = pd.read_csv(...)<br />df.tensorflow.to_tfrecord(output_dir="gs://my/bucket")</font></td></tr></tbody></table></div></span><br /><font face="courier">TFRecorder</font> currently expects data to be in the same format as Google <a href="https://cloud.google.com/vision/automl/docs/prepare" target="_blank">AutoML Vision</a>.<br /><br />This format looks like a pandas dataframe or CSV formatted as:<div><span id="docs-internal-guid-f9dbcd87-7fff-1de7-71c9-9c386216e22c"><div align="left" dir="ltr" style="margin-left: 0pt;"><table style="border-collapse: collapse; border: none;"><colgroup><col width="78"></col><col width="213"></col><col width="76"></col></colgroup><tbody><tr style="height: 23.25pt;"><td style="border-color: rgb(223, 226, 229); border-style: solid; border-width: 0.75pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt 10pt; text-align: center; vertical-align: top;"><b>split</b></td><td style="border-color: rgb(223, 226, 229); border-style: solid; border-width: 0.75pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt 10pt; text-align: center; vertical-align: top;"><b>image_uri</b></td><td style="border-color: rgb(223, 226, 229); border-style: solid; border-width: 0.75pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt 10pt; text-align: center; vertical-align: top;"><b>label</b></td></tr><tr style="height: 23.25pt;"><td style="border-color: rgb(223, 226, 229); border-style: solid; border-width: 0.75pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt 10pt; vertical-align: top;">TRAIN<br /></td><td style="border-color: rgb(223, 226, 229); border-style: solid; border-width: 0.75pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt 10pt; vertical-align: top;">gs://my/bucket/image1.jpg</td><td style="background-color: white; border-color: rgb(223, 226, 229); border-style: solid; border-width: 0.75pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt 10pt; vertical-align: top;">cat</td></tr></tbody></table></div></span><br />Where:<br /><ul style="text-align: left;"><li><font face="courier">split </font>can take on the values TRAIN, VALIDATION, and TEST</li><li><font face="courier">image_uri</font> specifies a local or google cloud storage location for the image file.</li><li><font face="courier">label</font> can be either a text-based label that will be integerized or an integer</li></ul>In the future, we hope to extend TensorFlow Recorder to work with data in any format. <br /><br />While this example would work well to convert a few thousand images into TFRecords, it probably wouldn&#8217;t scale well if you have millions of images. To scale up to huge datasets, TensorFlow Recorder provides connectivity with <a href="https://cloud.google.com/dataflow">Google Cloud Dataflow</a>, which is a serverless <a href="https://beam.apache.org/">Apache Beam</a> pipeline runner. Scaling up to DataFlow requires only a little bit more configuration.<div><span id="docs-internal-guid-0c153f02-7fff-45dc-0900-5ae709b51d9a"><div align="left" dir="ltr" style="margin-left: 0pt;"><table style="border-collapse: collapse; border: none; table-layout: fixed; width: 468pt;"><colgroup><col></col></colgroup><tbody><tr style="height: 0pt;"><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><font face="courier">df.tensorflow.to_tfrecord(<br />output_dir="gs://my/bucket",<br />runner="DataFlowRunner",<br />project="my-project",<br />region="us-central1)</font></td></tr></tbody></table></div></span><h2 style="text-align: left;">What&#8217;s next?</h2>We&#8217;d love for you to try out TensorFlow Recorder. You can get it from <a href="http://www.github.com/google/tensorflow-recorder" target="_blank">GitHub</a>&nbsp;or simply pip install <font face="courier">tfrecorder.</font> Tensorflow Recorder is very new and we&#8217;d greatly appreciate your feedback, suggestions, and pull requests. <br /><br /><i>By Mike Bernico and Carlos Ezequiel, Google Cloud AI Engineers</i><br /></div></div></div> <div style='clear: both;'></div> </div> </div> </div> <div class='post-footer'> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry uncustomized-post-template' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='https://lh6.googleusercontent.com/iIHjf5x7iPURWWMBj1ldoPgM6JI96PDNtRYRtT4dXimzPx_HRM1GViaq0CEA8aqPmS9lTGc6eCpHe8wyJ-J8r_wyv2AvVPUuPZXNWO7K2yfiXhqXMNk0mMtQEeWqiIrYOtkFOP0NQg' itemprop='image_url'/> <meta content='8698702854482141883' itemprop='blogId'/> <meta content='3704957168389926872' itemprop='postId'/> <a name='3704957168389926872'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='https://opensource.googleblog.com/2020/08/open-source-by-numbers-at-google.html'>Open source by the numbers at Google</a> </h3> <div class='post-header'> <h4 class='date-header'><span>Wednesday, August 5, 2020</span></h4> </div> <div class='post-body entry-content' id='post-body-3704957168389926872' itemprop='description articleBody'> At Google, open source is at the core of our infrastructure, processes, and culture. As such, participation in these communities is vital to our productivity. Within OSPO (Open Source Programs Office), our <a href="https://opensource.google/" target="_blank">mission</a> is to bring the value of open source to Google and the resources of Google to open source. To ensure our actions match our commitment, in this post we will explore a variety of metrics intended to increase context, transparency, and accountability across all of the communities we engage with.<br /><br /><b>Why we contribute: </b>Open source has become a pervasive component in modern software development, and Google is no exception. We use thousands of open source projects across our internal infrastructure and products. As participants in the ecosystem, our intentions are twofold: give back to the communities we depend on as well as expand support for open source overall. We firmly believe in open source and its ability to bring together users, contributors, and companies alike to deliver better software.<br /><br />The majority of Google&#8217;s open source work is done within one of two hosting platforms: GitHub and <a href="https://opensource.google/docs/glossary/#gitonborg" target="_blank">git-on-borg</a>, Google&#8217;s production Git service which integrates with <a href="https://gerrit.googlesource.com/gerrit/" target="_blank">Gerrit</a> for code review and access control. While we also allow individual usage of Bitbucket, GitLab, Launchpad, and other platforms, this analysis will focus on GitHub and git-on-borg. We will continue to explore how best to incorporate activity across additional channels.<br /><br />A little context about the numbers you&#8217;ll read below: <br /><ul style="text-align: left;"><li><b>Business and personal: </b>While git-on-borg hosts both internal and external Google created repos, GitHub is a mixture of Google projects, experimental efforts and personal projects created by Googlers. </li><li><b>Driven by humans: </b>We have created many automated bots and systems that can propose changes on both hosting platforms. We have intentionally filtered these data to ensure we are only showing human initiated activities.</li><li><b>GitHub data: </b>We are using <a href="https://www.gharchive.org/" target="_blank">GH Archive</a> as the primary source for GitHub data, which is currently available as a public dataset on <a href="https://cloud.google.com/bigquery" target="_blank">BigQuery</a>. Google activity within GitHub is identified by self registered accounts, which we anticipate under reports actual usage as employees acclimate to our <a href="https://opensource.google/docs/github/accounts/#register" target="_blank">policies</a>.</li><li><b>Active counts: </b>Where possible, we will show &#8216;active users&#8217; and &#8216;active repositories&#8217; defined by logged activity within each specified timeframe (for GH archive data, that&#8217;s any event type logged in the <a href="https://developer.github.com/v3/activity/events/" target="_blank">public GitHub event stream</a>).</li></ul>As numbers mean nothing without scale, let&#8217;s start by defining our applicable community: In 2019, more than 9% of Alphabet&#8217;s full time employees actively contributed to public repositories on git-on-borg and GitHub. While single digit, this percentage represents a portion of all full time Alphabet employees&#8212;from engineers to marketers to admins, across every business unit in Alphabet&#8212;and does not include those who contribute to open source projects outside of code. As our population has grown, so has our registered contributor base:<br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><img src="https://lh6.googleusercontent.com/iIHjf5x7iPURWWMBj1ldoPgM6JI96PDNtRYRtT4dXimzPx_HRM1GViaq0CEA8aqPmS9lTGc6eCpHe8wyJ-J8r_wyv2AvVPUuPZXNWO7K2yfiXhqXMNk0mMtQEeWqiIrYOtkFOP0NQg" style="margin-left: auto; margin-right: auto;" /></td></tr><tr><td class="tr-caption" style="text-align: center;">This chart shows the aggregate per year counts of Googlers active on public repositories hosted on GitHub and git-on-borg</td></tr></tbody></table><br /><b>What we create:</b> As mentioned above, our contributing population works across a variety of Google, personal, and external repositories. Over the years, Google has released thousands of <a href="https://opensource.google/">open source projects</a> (many of which span multiple repositories) and ~2,600 are still active. Today, Google hosts over 8,000 public repositories on GitHub and more than 1,000 public repositories on git-on-borg. Over the last five years, we have doubled the number of public repos, growing our footprint by an average of 25% per year.<br /><br /><b>What we work on: </b>In addition to our own repositories, we contribute to a wide pool of external projects. In 2019, Googlers were active in over 70,000 repositories on GitHub, pushing commits and/or opening pull requests on over 40,000 repositories. Note that more than 75% of the repos with Googler-opened pull requests were outside of Google-managed organizations (on GitHub).<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><img src="https://lh3.googleusercontent.com/emO-JgD8QaaN23guAP3mr7PHmYzqg1bbCOBUbWZchSF45mX3bmwSStkCwEN4UPYNPk2o5pQcMQN4qzwabPs4APwhYEJgDb6HN1BQpiIpyXKL_01S6zat3I5Th1-S8xDcRRkhBB9wPA=d" style="margin-left: auto; margin-right: auto;" /></td></tr><tr><td class="tr-caption" style="text-align: center;">This charts shows per year counts of activities initiated by Googlers on GitHub</td></tr></tbody></table><br /><b>What we contribute: </b>For contribution volume on GitHub, we chose to focus on <a href="https://developer.github.com/v3/activity/event_types/#pushevent" target="_blank">push events</a>, opened, and merged <a href="https://developer.github.com/v3/activity/event_types/#pullrequestevent" target="_blank">pull requests</a> instead of commits as this metric on its own is difficult to contextualize. Note that push events and pull requests typically include one or more commits per event. In 2019, Googlers created over 570,000 issues comments, opened over 150,000 pull requests, and created more than 36,000 push events on GitHub. Since 2015, we have doubled our annual counts of issues created and push events, and more than tripled the number of opened pull requests. Over the last five years, more than 80% of pull requests opened by Googlers have been closed and merged into active repositories. <br /><br /><div><b>How we spend our time:</b> Combining these two classes of metrics&#8212;contributions and repos&#8212;provides context on how our contributors focus their time. On GitHub: in 2015, about 40% of our opened pull requests were concentrated in just 25 repositories. However, over the next four years, our activity became more distributed across a larger set of projects, with the top 25 repos claiming about 20% of opened pull requests in 2019. For us, this indicates a healthy expansion and diversification of interests, especially given that this activity represents both Google, as well as a community of contributors that happen to work at Google.<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><img src="https://lh4.googleusercontent.com/rnPoYR3-Gpp_jYGQhSRE8Jx0XlyHddOqj0tJsfhiQmEltEqcHBLUmomt-R_M1ktd1VNsBiWLew1Iy6oBWR6z4MKK2CSd_toPoWvAPZ9UK62yLyUMeDce_2MtFS8Fuj7Fs2faa4qLAQ" style="margin-left: auto; margin-right: auto;" /></td></tr><tr><td class="tr-caption" style="text-align: center;">This chart splits the total per year counts of Googler created pull requests on GitHub by Top 25 repos vs the remainder ranked by number of opened pull requests per repo per year.</td></tr></tbody></table><h2 style="text-align: left;">Open source contribution is about more than code</h2>Every day, Google relies on the health and continuing availability of open source, and as such we actively invest in the security and sustainability of open source and its supply chain in three key areas: <br /><ul style="text-align: left;"><li><b>Security:</b> In addition to building security projects like <a href="https://opentitan.org/" target="_blank">OpenTitan</a> and <a href="https://gvisor.dev/" target="_blank">gVisor</a>, Google&#8217;s <a href="https://github.com/google/oss-fuzz" target="_blank">OSS-Fuzz</a> project aims to help other projects identify programming errors in software. As of the end of 2019, OSS-Fuzz had over <a href="https://github.com/google/oss-fuzz/tree/master/projects" target="_blank">250 projects</a> using the project, filed over <a href="https://bugs.chromium.org/p/oss-fuzz/issues/list?can=1&amp;q=-component%3AInfra%20-status%3AInvalid%2CWontFix%2CDuplicate&amp;colspec=ID%20Type%20Component%20Status%20Proj%20Reported%20Owner%20Summary&amp;cells=ids&amp;mode=chart&amp;start-date=2019-12-01&amp;end-date=2020-06-02" target="_blank">16,000 bugs</a>, including <a href="https://bugs.chromium.org/p/oss-fuzz/issues/list?can=1&amp;q=-component%3AInfra%20-status%3AInvalid%2CWontFix%2CDuplicate%20type%3DBug-Security&amp;colspec=ID%20Type%20Component%20Status%20Proj%20Reported%20Owner%20Summary&amp;cells=ids&amp;mode=chart&amp;start-date=2019-12-22&amp;end-date=2020-06-02">3,500 security vulnerabilities</a>.</li><li><b>Community:</b> Open source projects depend on communities of diverse individuals. We are committed to improving community sustainability and growth with programs like <a href="https://summerofcode.withgoogle.com/">Google Summer of Code</a> and <a href="https://developers.google.com/season-of-docs">Season of Docs</a>. Over the last 15 years, about 15,000 students from over 105 countries have participated in Google Summer of Code, along with 25,000 mentors in more than 115 countries working on more than 680 open source projects.</li><li><b>Research: </b>At the end of 2019, Google invested<a href="https://www.uvm.edu/uvmnews/news/university-vermont-complex-systems-center-advance-open-source-research-support-google" target="_blank"> $1 million in open source research</a>, partnering with<a href="https://vermontcomplexsystems.org/partner/OCEAN/" target="_blank"> researchers at UVM</a>, with the goal to deepen understanding of how people, teams and organizations thrive in technology-rich settings, especially in open-source projects and communities.</li></ul>Learn more about our open source initiatives at <a href="https://opensource.google/" target="_blank">opensource.google</a>.<br /><br /><i>By Sophia Vargas &#8211; Researcher, Google Open Source Programs Office</i></div> <div style='clear: both;'></div> </div> </div> </div> <div class='post-footer'> </div> </div></div> </div> <div class='blog-pager' id='blog-pager'> <a class='home-link' href='https://opensource.googleblog.com/'> <i class='material-icons'> &#59530; </i> </a> <span id='blog-pager-newer-link'> <a class='blog-pager-newer-link' href='https://opensource.googleblog.com/search?updated-max=2020-09-22T09:00:00-07:00&max-results=3&reverse-paginate=true' id='Blog1_blog-pager-newer-link' title='Newer Posts'> <i class='material-icons'> &#58820; </i> </a> </span> <span id='blog-pager-older-link'> <a class='blog-pager-older-link' href='https://opensource.googleblog.com/search?updated-max=2020-08-05T10:07:00-07:00&max-results=3' id='Blog1_blog-pager-older-link' title='Older Posts'> <i class='material-icons'> &#58824; </i> </a> </span> </div> <div class='clear'></div> <div class='clear'></div> </div></div> </div> </div> <div class='column-right-outer'> <div class='column-right-inner'> <aside> <div class='sidebar section' id='sidebar-right-1'><div class='widget HTML' data-version='1' id='HTML4'> <div class='widget-content'> <div class='searchBox'><input type='text' title='Search This Blog' placeholder='Search blog...' /></div> </div> <div class='clear'></div> </div><div class='widget PopularPosts' data-version='1' id='PopularPosts1'> <h2>Popular Posts</h2> <div class='widget-content popular-posts'> <ul> <li> <a href='https://opensource.googleblog.com/2023/06/rust-fact-vs-fiction-5-insights-from-googles-rust-journey-2022.html'>Rust fact vs. fiction: 5 Insights from Google's Rust journey in 2022</a> </li> <li> <a href='https://opensource.googleblog.com/2024/05/google-summer-of-code-2024-accepted-contributors-announced.html'>Google Summer of Code 2024 accepted contributors announced!</a> </li> <li> <a href='https://opensource.googleblog.com/2024/02/magika-ai-powered-fast-and-efficient-file-type-identification.html'>Magika: AI powered fast and efficient file type identification</a> </li> <li> <a href='https://opensource.googleblog.com/2024/04/introducing-jpegli-new-jpeg-coding-library.html'>Introducing Jpegli: A New JPEG Coding Library</a> </li> <li> <a href='https://opensource.googleblog.com/2023/11/google-summer-of-code-2024-celebrating-20th-year.html'>Google Summer of Code 2024 Celebrating our 20th Year!</a> </li> </ul> <div class='clear'></div> </div> </div><div class='widget BlogArchive' data-version='1' id='BlogArchive1'> <div class='tab'> <h2> Archive </h2> </div> <div class='widget-content'> <div id='ArchiveList'> <div id='BlogArchive1_ArchiveList'> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2024/'> 2024 </a> <span class='post-count'>(36)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2024/12/'> December </a> <span class='post-count'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2024/11/'> November </a> <span class='post-count'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2024/10/'> October </a> <span class='post-count'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2024/09/'> September </a> <span class='post-count'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2024/08/'> August </a> <span class='post-count'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2024/07/'> July </a> <span class='post-count'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2024/06/'> June </a> <span class='post-count'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2024/05/'> May </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2024/04/'> April </a> <span class='post-count'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2024/03/'> March </a> <span class='post-count'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2024/02/'> February </a> <span class='post-count'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2024/01/'> January </a> <span class='post-count'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2023/'> 2023 </a> <span class='post-count'>(44)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2023/12/'> December </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2023/11/'> November </a> <span class='post-count'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2023/10/'> October </a> <span class='post-count'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2023/09/'> September </a> <span class='post-count'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2023/08/'> August </a> <span class='post-count'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2023/07/'> July </a> <span class='post-count'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2023/06/'> June </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2023/05/'> May </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2023/04/'> April </a> <span class='post-count'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2023/03/'> March </a> <span class='post-count'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2023/02/'> February </a> <span class='post-count'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2023/01/'> January </a> <span class='post-count'>(4)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2022/'> 2022 </a> <span class='post-count'>(44)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2022/12/'> December </a> <span class='post-count'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2022/11/'> November </a> <span class='post-count'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2022/10/'> October </a> <span class='post-count'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2022/09/'> September </a> <span class='post-count'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2022/08/'> August </a> <span class='post-count'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2022/07/'> July </a> <span class='post-count'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2022/06/'> June </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2022/05/'> May </a> <span class='post-count'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2022/04/'> April </a> <span class='post-count'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2022/03/'> March </a> <span class='post-count'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2022/02/'> February </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2022/01/'> January </a> <span class='post-count'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2021/'> 2021 </a> <span class='post-count'>(55)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2021/12/'> December </a> <span class='post-count'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2021/11/'> November </a> <span class='post-count'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2021/10/'> October </a> <span class='post-count'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2021/09/'> September </a> <span class='post-count'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2021/08/'> August </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2021/06/'> June </a> <span class='post-count'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2021/05/'> May </a> <span class='post-count'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2021/04/'> April </a> <span class='post-count'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2021/03/'> March </a> <span class='post-count'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2021/02/'> February </a> <span class='post-count'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2021/01/'> January </a> <span class='post-count'>(5)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> &#9660;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2020/'> 2020 </a> <span class='post-count'>(83)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2020/12/'> December </a> <span class='post-count'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2020/11/'> November </a> <span class='post-count'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2020/10/'> October </a> <span class='post-count'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2020/09/'> September </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> &#9660;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2020/08/'> August </a> <span class='post-count'>(13)</span> <ul class='posts'> <li><a href='https://opensource.googleblog.com/2020/08/new-case-studies-about-googles-use-of-go.html'>New Case Studies About Google&#8217;s Use of Go</a></li> <li><a href='https://opensource.googleblog.com/2020/08/recapping-major-improvements-in-go-115.html'>Recapping major improvements in Go 1.15 and bringi...</a></li> <li><a href='https://opensource.googleblog.com/2020/08/google-open-source-live-monthly.html'>Google Open Source Live: A monthly connection for ...</a></li> <li><a href='https://opensource.googleblog.com/2020/08/assess-security-of-cloud-deployments.html'>Assess the security of Cloud deployments with InSp...</a></li> <li><a href='https://opensource.googleblog.com/2020/08/cloud-spanner-emulator-reaches-10.html'>Cloud Spanner Emulator Reaches 1.0 Milestone!</a></li> <li><a href='https://opensource.googleblog.com/2020/08/defcon-differential-privacy-training.html'>DEFCON Differential Privacy Training Launch</a></li> <li><a href='https://opensource.googleblog.com/2020/08/season-of-docs-announces-2020-technical.html'>Season of Docs announces 2020 technical writing pr...</a></li> <li><a href='https://opensource.googleblog.com/2020/08/java-zpages-for-opentelemetry.html'>Java zPages for OpenTelemetry</a></li> <li><a href='https://opensource.googleblog.com/2020/08/google-summer-of-code-2020-statistics.html'>Google Summer of Code 2020 Statistics: Part 2</a></li> <li><a href='https://opensource.googleblog.com/2020/08/supporting-wikipedia-with-more-tools.html'>Supporting Wikipedia with more tools for editors</a></li> <li><a href='https://opensource.googleblog.com/2020/08/introducing-tensorflow-recorder.html'>Introducing TensorFlow Recorder</a></li> <li><a href='https://opensource.googleblog.com/2020/08/open-source-by-numbers-at-google.html'>Open source by the numbers at Google</a></li> <li><a href='https://opensource.googleblog.com/2020/08/google-joins-open-source-security.html'>Google joins the Open Source Security Foundation</a></li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2020/07/'> July </a> <span class='post-count'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2020/06/'> June </a> <span class='post-count'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2020/05/'> May </a> <span class='post-count'>(9)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2020/04/'> April </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2020/03/'> March </a> <span class='post-count'>(13)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2020/02/'> February </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2020/01/'> January </a> <span class='post-count'>(5)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2019/'> 2019 </a> <span class='post-count'>(65)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2019/12/'> December </a> <span class='post-count'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2019/11/'> November </a> <span class='post-count'>(9)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2019/10/'> October </a> <span class='post-count'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2019/09/'> September </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2019/08/'> August </a> <span class='post-count'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2019/07/'> July </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2019/06/'> June </a> <span class='post-count'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2019/05/'> May </a> <span class='post-count'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2019/04/'> April </a> <span class='post-count'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2019/03/'> March </a> <span class='post-count'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2019/02/'> February </a> <span class='post-count'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2019/01/'> January </a> <span class='post-count'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2018/'> 2018 </a> <span class='post-count'>(59)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2018/12/'> December </a> <span class='post-count'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2018/11/'> November </a> <span class='post-count'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2018/10/'> October </a> <span class='post-count'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2018/09/'> September </a> <span class='post-count'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2018/08/'> August </a> <span class='post-count'>(10)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2018/07/'> July </a> <span class='post-count'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2018/06/'> June </a> <span class='post-count'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2018/05/'> May </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2018/04/'> April </a> <span class='post-count'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2018/03/'> March </a> <span class='post-count'>(16)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2018/02/'> February </a> <span class='post-count'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2018/01/'> January </a> <span class='post-count'>(8)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2017/'> 2017 </a> <span class='post-count'>(73)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2017/12/'> December </a> <span class='post-count'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2017/11/'> November </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2017/10/'> October </a> <span class='post-count'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2017/09/'> September </a> <span class='post-count'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2017/08/'> August </a> <span class='post-count'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2017/07/'> July </a> <span class='post-count'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2017/06/'> June </a> <span class='post-count'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2017/05/'> May </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2017/04/'> April </a> <span class='post-count'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2017/03/'> March </a> <span class='post-count'>(13)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2017/02/'> February </a> <span class='post-count'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2017/01/'> January </a> <span class='post-count'>(13)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2016/'> 2016 </a> <span class='post-count'>(85)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2016/12/'> December </a> <span class='post-count'>(9)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2016/11/'> November </a> <span class='post-count'>(13)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2016/10/'> October </a> <span class='post-count'>(13)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2016/09/'> September </a> <span class='post-count'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2016/08/'> August </a> <span class='post-count'>(9)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2016/07/'> July </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2016/06/'> June </a> <span class='post-count'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2016/05/'> May </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2016/04/'> April </a> <span class='post-count'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2016/03/'> March </a> <span class='post-count'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2016/02/'> February </a> <span class='post-count'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2016/01/'> January </a> <span class='post-count'>(4)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2015/'> 2015 </a> <span class='post-count'>(80)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2015/12/'> December </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2015/11/'> November </a> <span class='post-count'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2015/10/'> October </a> <span class='post-count'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2015/09/'> September </a> <span class='post-count'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2015/08/'> August </a> <span class='post-count'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2015/07/'> July </a> <span class='post-count'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2015/06/'> June </a> <span class='post-count'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2015/05/'> May </a> <span class='post-count'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2015/04/'> April </a> <span class='post-count'>(10)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2015/03/'> March </a> <span class='post-count'>(10)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2015/02/'> February </a> <span class='post-count'>(11)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2015/01/'> January </a> <span class='post-count'>(8)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2014/'> 2014 </a> <span class='post-count'>(104)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2014/12/'> December </a> <span class='post-count'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2014/11/'> November </a> <span class='post-count'>(12)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2014/10/'> October </a> <span class='post-count'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2014/09/'> September </a> <span class='post-count'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2014/08/'> August </a> <span class='post-count'>(9)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2014/07/'> July </a> <span class='post-count'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2014/06/'> June </a> <span class='post-count'>(10)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2014/05/'> May </a> <span class='post-count'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2014/04/'> April </a> <span class='post-count'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2014/03/'> March </a> <span class='post-count'>(11)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2014/02/'> February </a> <span class='post-count'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2014/01/'> January </a> <span class='post-count'>(10)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2013/'> 2013 </a> <span class='post-count'>(100)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2013/12/'> December </a> <span class='post-count'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2013/11/'> November </a> <span class='post-count'>(10)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2013/10/'> October </a> <span class='post-count'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2013/09/'> September </a> <span class='post-count'>(9)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2013/08/'> August </a> <span class='post-count'>(10)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2013/07/'> July </a> <span class='post-count'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2013/06/'> June </a> <span class='post-count'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2013/05/'> May </a> <span class='post-count'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2013/04/'> April </a> <span class='post-count'>(10)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2013/03/'> March </a> <span class='post-count'>(9)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2013/02/'> February </a> <span class='post-count'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2013/01/'> January </a> <span class='post-count'>(8)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2012/'> 2012 </a> <span class='post-count'>(93)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2012/12/'> December </a> <span class='post-count'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2012/11/'> November </a> <span class='post-count'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2012/10/'> October </a> <span class='post-count'>(9)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2012/09/'> September </a> <span class='post-count'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2012/08/'> August </a> <span class='post-count'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2012/07/'> July </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2012/06/'> June </a> <span class='post-count'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2012/05/'> May </a> <span class='post-count'>(10)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2012/04/'> April </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2012/03/'> March </a> <span class='post-count'>(15)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2012/02/'> February </a> <span class='post-count'>(9)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2012/01/'> January </a> <span class='post-count'>(7)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2011/'> 2011 </a> <span class='post-count'>(117)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2011/12/'> December </a> <span class='post-count'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2011/11/'> November </a> <span class='post-count'>(14)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2011/10/'> October </a> <span class='post-count'>(13)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2011/09/'> September </a> <span class='post-count'>(10)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2011/08/'> August </a> <span class='post-count'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2011/07/'> July </a> <span class='post-count'>(13)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2011/06/'> June </a> <span class='post-count'>(11)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2011/05/'> May </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2011/04/'> April </a> <span class='post-count'>(11)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2011/03/'> March </a> <span class='post-count'>(10)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2011/02/'> February </a> <span class='post-count'>(10)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2011/01/'> January </a> <span class='post-count'>(7)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2010/'> 2010 </a> <span class='post-count'>(123)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2010/12/'> December </a> <span class='post-count'>(9)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2010/11/'> November </a> <span class='post-count'>(12)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2010/10/'> October </a> <span class='post-count'>(10)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2010/09/'> September </a> <span class='post-count'>(14)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2010/08/'> August </a> <span class='post-count'>(10)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2010/07/'> July </a> <span class='post-count'>(7)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2010/06/'> June </a> <span class='post-count'>(10)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2010/05/'> May </a> <span class='post-count'>(11)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2010/04/'> April </a> <span class='post-count'>(14)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2010/03/'> March </a> <span class='post-count'>(13)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2010/02/'> February </a> <span class='post-count'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2010/01/'> January </a> <span class='post-count'>(5)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2009/'> 2009 </a> <span class='post-count'>(124)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2009/12/'> December </a> <span class='post-count'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2009/11/'> November </a> <span class='post-count'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2009/10/'> October </a> <span class='post-count'>(11)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2009/09/'> September </a> <span class='post-count'>(11)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2009/08/'> August </a> <span class='post-count'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2009/07/'> July </a> <span class='post-count'>(13)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2009/06/'> June </a> <span class='post-count'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2009/05/'> May </a> <span class='post-count'>(11)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2009/04/'> April </a> <span class='post-count'>(16)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2009/03/'> March </a> <span class='post-count'>(17)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2009/02/'> February </a> <span class='post-count'>(10)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2009/01/'> January </a> <span class='post-count'>(10)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2008/'> 2008 </a> <span class='post-count'>(167)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2008/12/'> December </a> <span class='post-count'>(10)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2008/11/'> November </a> <span class='post-count'>(11)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2008/10/'> October </a> <span class='post-count'>(13)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2008/09/'> September </a> <span class='post-count'>(16)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2008/08/'> August </a> <span class='post-count'>(12)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2008/07/'> July </a> <span class='post-count'>(20)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2008/06/'> June </a> <span class='post-count'>(14)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2008/05/'> May </a> <span class='post-count'>(21)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2008/04/'> April </a> <span class='post-count'>(16)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2008/03/'> March </a> <span class='post-count'>(17)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://opensource.googleblog.com/2008/02/'> February </a> <span class='post-count'>(17)</span> </li> </ul> </li> </ul> </div> </div> <div class='clear'></div> </div> </div><div class='widget HTML' data-version='1' id='HTML3'> <div class='widget-content'> <div class="share"> <a href="https://twitter.com/GoogleOSS"><img alt="Twitter" height="24" src="https://www.gstatic.com/images/icons/material/system/2x/post_twitter_black_24dp.png" width="24" /></a> <a href="https://www.youtube.com/GoogleOpenSource"><img alt="YouTube" height="24" src="https://www.gstatic.com/images/icons/material/system/2x/post_youtube_black_24dp.png" width="24" /></a> </div> </div> <div class='clear'></div> </div></div> </aside> </div> </div> </div> <div style='clear: both'></div> </div> </div> </div> </section> </div> <footer class='footer-main' id='FooterMain'> <div class='col-wrap'> <nav class='footer-nav pull-left'> <ul> <li class='google'> <a href="//google.com" title="Google"> Google </a> </li> <li> <a href='https://www.google.com/policies/privacy/' title='Privacy'> Privacy </a> </li> <li> <a href='https://www.google.com/policies/terms/' title='Terms'> Terms </a> </li> </ul> </nav> </div> </footer> </div> <div id='ogc-shim'> <a href='#' id='SendFeedback'>.</a> </div> <script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script> <script async='async' src='https://support.google.com/inapp/api.js' type='text/javascript'></script> <script type='text/javascript'> //<![CDATA[ $(document).ready(function(){ var DocEl = document.documentElement; DocEl.className = DocEl.className.replace('no-js', 'js'); var NavTriggerEl = document.getElementById("NavTrigger"); var BodyEl = document.body; var ShadowBoxEl = document.createElement("div"); ShadowBoxEl.id = "ShadowBox"; BodyEl.appendChild(ShadowBoxEl); NavTriggerEl.addEventListener("click", function(e){ e.preventDefault(); toggleActiveClass(); }); ShadowBoxEl.addEventListener("click", function(){ toggleActiveClass(); }); $('a:not(.internal):not([href^="https://opensource.googleblog.com"]):not([href^="http://opensource.googleblog.com"]):not([href^="https://opensource.google.com"]):not([href^="http://opensource.google.com"]):not([href^="#"]):not([href^="/"]):not([href^="javascript"]):not([href^="mailto"])').addClass('external'); $('a.external').attr("target", "_blank"); }); // Social sharing popups. var postEl = document.getElementsByClassName('social-wrapper'); var postCount = postEl.length; for(i=0; i<postCount;i++){ postEl[i].addEventListener("click", function(event){ var postUrl = this.getAttribute("data-href"); window.open( postUrl,'popUpWindow','height=500,width=500,left=10,top=10,resizable=yes,scrollbars=yes,toolbar=yes,menubar=no,location=no,directories=no,status=yes'); });} var postEl = document.getElementsByClassName('social-wrapper2'); var postCount = postEl.length; for(i=0; i<postCount;i++){ postEl[i].addEventListener("click", function(event){ var postUrl = this.getAttribute("data-href"); window.open( postUrl,'popUpWindow2','height=500,width=400,left=10,top=10,resizable=yes,scrollbars=yes,toolbar=yes,menubar=no,location=no,directories=no,status=yes'); });} function toggleActiveClass() { var stringIndex = document.body.className.indexOf("nav-active"); if (stringIndex < 0) { document.body.className += " nav-active"; } else { document.body.className = document.body.className.replace(" nav-active", ""); } } //]]> </script> <script type='text/javascript'> //<![CDATA[ var BreakpointHandler = function() { this.initted = false; this.isHomePage = false; this.isMobile = false; }; BreakpointHandler.prototype.finalizeSummary = function(summaryHtml, lastNode) { // Use $.trim for IE8 compatibility summaryHtml = $.trim(summaryHtml).replace(/(<br>|\s)+$/,''); if (lastNode.nodeType == 3) { var lastChar = summaryHtml.slice(-1); if (!lastChar.match(/[.”"?]/)) { if (!lastChar.match(/[A-Za-z]/)) { summaryHtml = summaryHtml.slice(0, -1); } summaryHtml += ' ...'; } } else if (lastNode.nodeType == 1 && (lastNode.nodeName == 'I' || lastNode.nodeName == 'A')) { summaryHtml += ' ...'; } return summaryHtml; }; BreakpointHandler.prototype.generateSummaryFromContent = function(content, numWords) { var seenWords = 0; var summaryHtml = ''; for (var i=0; i < content.childNodes.length; i++) { var node = content.childNodes[i]; var nodeText; if (node.nodeType == 1) { if (node.hasAttribute('data-about-pullquote')) { continue; } nodeText = node.textContent; if (nodeText === undefined) { // innerText for IE8 nodeText = node.innerText; } if (node.nodeName == 'DIV' || node.nodeName == 'B') { // Don't end early if we haven't seen enough words. if (seenWords < 10) { continue; } if (i > 0) { summaryHtml = this.finalizeSummary(summaryHtml, content.childNodes[i-1]); } break; } summaryHtml += node.outerHTML; } else if (node.nodeType == 3) { nodeText = node.nodeValue; summaryHtml += nodeText + ' '; } var words = nodeText.match(/\S+\s*/g); if (!words) { continue; } var remain = numWords - seenWords; if (words.length >= remain) { summaryHtml = this.finalizeSummary(summaryHtml, node); break; } seenWords += words.length; } return summaryHtml; }; BreakpointHandler.prototype.detect = function() { var match, pl = /\+/g, search = /([^&=]+)=?([^&]*)/g, decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); }, query = window.location.search.substring(1); var urlParams = {}; while (match = search.exec(query)) urlParams[decode(match[1])] = decode(match[2]); this.isListPage = $('html').hasClass('list-page'); this.isMobile = urlParams['m'] === '1'; this.isHomePage = window.location.pathname == '/'; }; BreakpointHandler.prototype.initContent = function() { var self = this; $('.post').each(function(index) { var body = $(this).children('.post-body')[0]; /*var content = $(body).children('.post-content')[0];*/ // XXX does not exist var content = body; $(content).addClass('post-original'); var data = $(content).children('script').html(); // XXX added this if block because data never seems to exist if (data) { data = self.rewriteForSSL(data); // If exists, extract specified editor's preview. var match = data.match(/([\s\S]+?)<div data-is-preview.+?>([\s\S]+)<\/div>/m); if (match) { data = match[1]; } // Prevent big images from loading when they aren't needed. // This must be done as a pre-injection step, since image loading can't be // canceled once embedded into the DOM. if (self.isListPage && self.isMobile) { data = data.replace(/<(img|iframe) .+?>/g, ''); } // Insert template to be rendered as nodes. content.innerHTML = data; } if (self.isListPage) { var summary = document.createElement('div'); $(summary).addClass('post-content'); $(summary).addClass('post-summary'); body.insertBefore(summary, content); if (match) { // Use provided summary. summary.innerHTML = match[2]; } else { // Generate a summary. // Summary generation relies on DOM, so it must occur after content is // inserted into the page. summary.innerHTML = self.generateSummaryFromContent(content, 30); } // Add read more link to summary. var titleAnchor = $(this).find('.title a')[0]; var link = titleAnchor.cloneNode(true); link.innerHTML = 'Read More'; $(link).addClass('read-more'); summary.appendChild(link); } }); // Firefox does not allow for proper styling of BR. if (navigator.userAgent.indexOf('Firefox') > -1) { $('.post-content br').replaceWith('<span class="space"></span>'); } }; BreakpointHandler.prototype.process = function() { if (!this.initted) { var makeInsecureImageRegex = function(hosts) { var whitelist = hosts.join('|').replace(/\./g,'\\.'); // Normal image tags, plus input images (yes, this is possible!) return new RegExp('(<(img|input)[^>]+?src=("|\'))http:\/\/(' + whitelist +')', 'g'); }; this.sslImageRegex = makeInsecureImageRegex(BreakpointHandler.KNOWN_HTTPS_HOSTS); this.sslImageCurrentDomainRegex = makeInsecureImageRegex([window.location.hostname]); this.detect(); this.initContent(); this.initted = true; } }; BreakpointHandler.KNOWN_HTTPS_HOSTS = [ "opensource.google.com", "www.google.org", "www.google.com", "services.google.com", "blogger.com", "draft.blogger.com", "www.blogger.com", "photos1.blogger.com", "photos2.blogger.com", "photos3.blogger.com", "blogblog.com", "img1.blogblog.com", "img2.blogblog.com", "www.blogblog.com", "www1.blogblog.com", "www2.blogblog.com", "0.bp.blogspot.com", "1.bp.blogspot.com", "2.bp.blogspot.com", "3.bp.blogspot.com", "4.bp.blogspot.com", "lh3.googleusercontent.com", "lh4.googleusercontent.com", "lh5.googleusercontent.com", "lh6.googleusercontent.com", "themes.googleusercontent.com", ]; BreakpointHandler.prototype.rewriteForSSL = function(html) { // Handle HTTP -> HTTPS source replacement of images, movies, and other embedded content. return html.replace(this.sslImageRegex, '$1https://$4') .replace(this.sslImageCurrentDomainRegex, '$1//$4') .replace(/(<(embed|iframe)[^>]+?src=("|'))http:\/\/([^"']*?(youtube|picasaweb\.google)\.com)/g, '$1https://$4') // Slideshow SWF takes a image host, so we need to rewrite that parameter. .replace(/(<embed[^>]+?feed=http(?=[^s]))/g, '$1s'); }; $(document).ready(function() { var handler = new BreakpointHandler(); handler.process(); // Top-level navigation. $(".BlogArchive .tab").click(function(ev) { ev.preventDefault(); $(this).parent().toggleClass('active'); if ($(this).parent().hasClass('active')) { $(this).siblings().css('display', 'block'); } else { $(this).siblings().css('display', 'none'); } }); $(".Label .tab").click(function(ev) { ev.preventDefault(); $(this).parent().toggleClass('active'); if ($(this).parent().hasClass('active')) { $(this).siblings().css('display', 'block'); } else { $(this).siblings().css('display', 'none'); } }); // Blog archive year expansion. $('.BlogArchive .intervalToggle').click(function(ev) { ev.preventDefault(); if ($(this).parent().hasClass('collapsed')) { $(this).parent().removeClass('collapsed'); $(this).parent().addClass('expanded'); } else { $(this).parent().removeClass('expanded'); $(this).parent().addClass('collapsed'); } }); // Reverse order of months. $('.BlogArchive .intervalToggle + div').each(function(_, items) { var year = $(this); year.children().each(function(_, month) { year.prepend(month); }); }); // Process search requests. $('.searchBox input').on("keypress", function(ev) { if (ev.which == 13) { window.location.href = 'https://www.google.com/search?q=site%3A' + window.location.hostname + '%20' + encodeURIComponent ($(this).val()); } }); }); //]]> </script> <link href='https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.css' rel='stylesheet' type='text/css'/> <script language='javascript' src='https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.js' type='text/javascript'></script> <script language='javascript' src='https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/lang-css.min.js' type='text/javascript'></script> <script type='text/javascript'> document.addEventListener('DOMContentLoaded',function() { prettyPrint(); }); </script> <script type='text/javascript'> //<![CDATA[ (function(){var f,aa="function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){if(c.get||c.set)throw new TypeError("ES3 does not support getters and setters.");a!=Array.prototype&&a!=Object.prototype&&(a[b]=c.value)},k="undefined"!=typeof window&&window===this?this:"undefined"!=typeof global&&null!=global?global:this;function ba(){ba=function(){};k.Symbol||(k.Symbol=ca)}var da=0;function ca(a){return"jscomp_symbol_"+(a||"")+da++} function l(){ba();var a=k.Symbol.iterator;a||(a=k.Symbol.iterator=k.Symbol("iterator"));"function"!=typeof Array.prototype[a]&&aa(Array.prototype,a,{configurable:!0,writable:!0,value:function(){return ea(this)}});l=function(){}}function ea(a){var b=0;return fa(function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}})}function fa(a){l();a={next:a};a[k.Symbol.iterator]=function(){return this};return a} function m(a){if(!(a instanceof Array)){l();var b=a[Symbol.iterator];a=b?b.call(a):ea(a);for(var c=[];!(b=a.next()).done;)c.push(b.value);a=c}return a}function ha(a,b){function c(){}c.prototype=b.prototype;a.ha=b.prototype;a.prototype=new c;a.prototype.constructor=a;for(var d in b)if(Object.defineProperties){var e=Object.getOwnPropertyDescriptor(b,d);e&&Object.defineProperty(a,d,e)}else a[d]=b[d]} var n=window.Element.prototype,ia=n.matches||n.matchesSelector||n.webkitMatchesSelector||n.mozMatchesSelector||n.msMatchesSelector||n.oMatchesSelector;function ja(a,b){if(a&&1==a.nodeType&&b){if("string"==typeof b||1==b.nodeType)return a==b||ka(a,b);if("length"in b)for(var c=0,d;d=b[c];c++)if(a==d||ka(a,d))return!0}return!1}function ka(a,b){if("string"!=typeof b)return!1;if(ia)return ia.call(a,b);b=a.parentNode.querySelectorAll(b);for(var c=0,d;d=b[c];c++)if(d==a)return!0;return!1} function la(a){for(var b=[];a&&a.parentNode&&1==a.parentNode.nodeType;)a=a.parentNode,b.push(a);return b} function p(a,b,c){function d(a){var d;if(h.composed&&"function"==typeof a.composedPath)for(var e=a.composedPath(),g=0,E;E=e[g];g++)1==E.nodeType&&ja(E,b)&&(d=E);else a:{if((d=a.target)&&1==d.nodeType&&b)for(d=[d].concat(la(d)),e=0;g=d[e];e++)if(ja(g,b)){d=g;break a}d=void 0}d&&c.call(d,a,d)}var e=document,h={composed:!0,S:!0},h=void 0===h?{}:h;e.addEventListener(a,d,h.S);return{j:function(){e.removeEventListener(a,d,h.S)}}} function ma(a){var b={};if(!a||1!=a.nodeType)return b;a=a.attributes;if(!a.length)return{};for(var c=0,d;d=a[c];c++)b[d.name]=d.value;return b}var na=/:(80|443)$/,q=document.createElement("a"),r={}; function t(a){a=a&&"."!=a?a:location.href;if(r[a])return r[a];q.href=a;if("."==a.charAt(0)||"/"==a.charAt(0))return t(q.href);var b="80"==q.port||"443"==q.port?"":q.port,b="0"==b?"":b,c=q.host.replace(na,"");return r[a]={hash:q.hash,host:c,hostname:q.hostname,href:q.href,origin:q.origin?q.origin:q.protocol+"//"+c,pathname:"/"==q.pathname.charAt(0)?q.pathname:"/"+q.pathname,port:b,protocol:q.protocol,search:q.search}}var u=[]; function oa(a,b){var c=this;this.context=a;this.P=b;this.f=(this.c=/Task$/.test(b))?a.get(b):a[b];this.b=[];this.a=[];this.g=function(a){for(var b=[],d=0;d<arguments.length;++d)b[d-0]=arguments[d];return c.a[c.a.length-1].apply(null,[].concat(m(b)))};this.c?a.set(b,this.g):a[b]=this.g}function v(a,b,c){a=pa(a,b);a.b.push(c);qa(a)}function w(a,b,c){a=pa(a,b);c=a.b.indexOf(c);-1<c&&(a.b.splice(c,1),0<a.b.length?qa(a):a.j())} function qa(a){a.a=[];for(var b,c=0;b=a.b[c];c++){var d=a.a[c-1]||a.f.bind(a.context);a.a.push(b(d))}}oa.prototype.j=function(){var a=u.indexOf(this);-1<a&&(u.splice(a,1),this.c?this.context.set(this.P,this.f):this.context[this.P]=this.f)};function pa(a,b){var c=u.filter(function(c){return c.context==a&&c.P==b})[0];c||(c=new oa(a,b),u.push(c));return c} function x(a,b,c,d,e,h){if("function"==typeof d){var g=c.get("buildHitTask");return{buildHitTask:function(c){c.set(a,null,!0);c.set(b,null,!0);d(c,e,h);g(c)}}}return y({},a,b)}function z(a,b){var c=ma(a),d={};Object.keys(c).forEach(function(a){if(!a.indexOf(b)&&a!=b+"on"){var e=c[a];"true"==e&&(e=!0);"false"==e&&(e=!1);a=ra(a.slice(b.length));d[a]=e}});return d} function sa(a){"loading"==document.readyState?document.addEventListener("DOMContentLoaded",function c(){document.removeEventListener("DOMContentLoaded",c);a()}):a()}function ta(a,b){var c;return function(d){for(var e=[],h=0;h<arguments.length;++h)e[h-0]=arguments[h];clearTimeout(c);c=setTimeout(function(){return a.apply(null,[].concat(m(e)))},b)}}function ua(a){function b(){c||(c=!0,a())}var c=!1;setTimeout(b,2E3);return b}var A={}; function va(a,b){function c(){clearTimeout(e.timeout);e.send&&w(a,"send",e.send);delete A[d];e.R.forEach(function(a){return a()})}var d=a.get("trackingId"),e=A[d]=A[d]||{};clearTimeout(e.timeout);e.timeout=setTimeout(c,0);e.R=e.R||[];e.R.push(b);e.send||(e.send=function(a){return function(b){for(var d=[],e=0;e<arguments.length;++e)d[e-0]=arguments[e];c();a.apply(null,[].concat(m(d)))}},v(a,"send",e.send))} var y=Object.assign||function(a,b){for(var c=[],d=1;d<arguments.length;++d)c[d-1]=arguments[d];for(var d=0,e=c.length;d<e;d++){var h=Object(c[d]),g;for(g in h)Object.prototype.hasOwnProperty.call(h,g)&&(a[g]=h[g])}return a};function ra(a){return a.replace(/[\-\_]+(\w?)/g,function(a,c){return c.toUpperCase()})}function B(a){return"object"==typeof a&&null!==a}var C=function wa(b){return b?(b^16*Math.random()>>b/4).toString(16):"10000000-1000-4000-8000-100000000000".replace(/[018]/g,wa)}; function F(a,b){var c=window.GoogleAnalyticsObject||"ga";window[c]=window[c]||function(a){for(var b=[],d=0;d<arguments.length;++d)b[d-0]=arguments[d];(window[c].q=window[c].q||[]).push(b)};window.gaDevIds=window.gaDevIds||[];0>window.gaDevIds.indexOf("i5iSjo")&&window.gaDevIds.push("i5iSjo");window[c]("provide",a,b);window.gaplugins=window.gaplugins||{};window.gaplugins[a.charAt(0).toUpperCase()+a.slice(1)]=b}var G={T:1,U:2,V:3,X:4,Y:5,Z:6,$:7,aa:8,ba:9,W:10},H=Object.keys(G).length; function I(a,b){a.set("\x26_av","2.3.3");var c=a.get("\x26_au"),c=parseInt(c||"0",16).toString(2);if(c.length<H)for(var d=H-c.length;d;)c="0"+c,d--;b=H-b;c=c.substr(0,b)+1+c.substr(b+1);a.set("\x26_au",parseInt(c||"0",2).toString(16))}function J(a,b){I(a,G.T);this.a=y({},b);this.g=a;this.b=this.a.stripQuery&&this.a.queryDimensionIndex?"dimension"+this.a.queryDimensionIndex:null;this.f=this.f.bind(this);this.c=this.c.bind(this);v(a,"get",this.f);v(a,"buildHitTask",this.c)} J.prototype.f=function(a){var b=this;return function(c){if("page"==c||c==b.b){var d={location:a("location"),page:a("page")};return xa(b,d)[c]}return a(c)}};J.prototype.c=function(a){var b=this;return function(c){var d=xa(b,{location:c.get("location"),page:c.get("page")});c.set(d,null,!0);a(c)}}; function xa(a,b){var c=t(b.page||b.location),d=c.pathname;if(a.a.indexFilename){var e=d.split("/");a.a.indexFilename==e[e.length-1]&&(e[e.length-1]="",d=e.join("/"))}"remove"==a.a.trailingSlash?d=d.replace(/\/+$/,""):"add"==a.a.trailingSlash&&(/\.\w+$/.test(d)||"/"==d.substr(-1)||(d+="/"));d={page:d+(a.a.stripQuery?"":c.search)};b.location&&(d.location=b.location);a.b&&(d[a.b]=c.search.slice(1)||"(not set)");return"function"==typeof a.a.urlFieldsFilter?(b=a.a.urlFieldsFilter(d,t),c={},c.page=b.page, c.location=b.location,c[a.b]=b[a.b],c):d}J.prototype.remove=function(){w(this.g,"get",this.f);w(this.g,"buildHitTask",this.c)};F("cleanUrlTracker",J);function K(a,b){var c=this;I(a,G.U);if(window.addEventListener){this.a=y({events:["click"],fieldsObj:{},attributePrefix:"ga-"},b);this.f=a;this.c=this.c.bind(this);var d="["+this.a.attributePrefix+"on]";this.b={};this.a.events.forEach(function(a){c.b[a]=p(a,d,c.c)})}} K.prototype.c=function(a,b){var c=this.a.attributePrefix;if(!(0>b.getAttribute(c+"on").split(/\s*,\s*/).indexOf(a.type))){var c=z(b,c),d=y({},this.a.fieldsObj,c);this.f.send(c.hitType||"event",x({transport:"beacon"},d,this.f,this.a.hitFilter,b,a))}};K.prototype.remove=function(){var a=this;Object.keys(this.b).forEach(function(b){a.b[b].j()})};F("eventTracker",K); function ya(a,b){var c=this;I(a,G.V);window.IntersectionObserver&&window.MutationObserver&&(this.a=y({rootMargin:"0px",fieldsObj:{},attributePrefix:"ga-"},b),this.c=a,this.M=this.M.bind(this),this.O=this.O.bind(this),this.K=this.K.bind(this),this.L=this.L.bind(this),this.b=null,this.items=[],this.i={},this.h={},sa(function(){c.a.elements&&c.observeElements(c.a.elements)}))}f=ya.prototype; f.observeElements=function(a){var b=this;a=L(this,a);this.items=this.items.concat(a.items);this.i=y({},a.i,this.i);this.h=y({},a.h,this.h);a.items.forEach(function(a){var c=b.h[a.threshold]=b.h[a.threshold]||new IntersectionObserver(b.O,{rootMargin:b.a.rootMargin,threshold:[+a.threshold]});(a=b.i[a.id]||(b.i[a.id]=document.getElementById(a.id)))&&c.observe(a)});this.b||(this.b=new MutationObserver(this.M),this.b.observe(document.body,{childList:!0,subtree:!0}));requestAnimationFrame(function(){})}; f.unobserveElements=function(a){var b=[],c=[];this.items.forEach(function(d){a.some(function(a){a=za(a);return a.id===d.id&&a.threshold===d.threshold&&a.trackFirstImpressionOnly===d.trackFirstImpressionOnly})?c.push(d):b.push(d)});if(b.length){var d=L(this,b),e=L(this,c);this.items=d.items;this.i=d.i;this.h=d.h;c.forEach(function(a){if(!d.i[a.id]){var b=e.h[a.threshold],c=e.i[a.id];c&&b.unobserve(c);d.h[a.threshold]||e.h[a.threshold].disconnect()}})}else this.unobserveAllElements()}; f.unobserveAllElements=function(){var a=this;Object.keys(this.h).forEach(function(b){a.h[b].disconnect()});this.b.disconnect();this.b=null;this.items=[];this.i={};this.h={}};function L(a,b){var c=[],d={},e={};b.length&&b.forEach(function(b){b=za(b);c.push(b);e[b.id]=a.i[b.id]||null;d[b.threshold]=a.h[b.threshold]||null});return{items:c,i:e,h:d}}f.M=function(a){for(var b=0,c;c=a[b];b++){for(var d=0,e;e=c.removedNodes[d];d++)M(this,e,this.L);for(d=0;e=c.addedNodes[d];d++)M(this,e,this.K)}}; function M(a,b,c){1==b.nodeType&&b.id in a.i&&c(b.id);for(var d=0,e;e=b.childNodes[d];d++)M(a,e,c)} f.O=function(a){for(var b=[],c=0,d;d=a[c];c++)for(var e=0,h;h=this.items[e];e++){var g;if(g=d.target.id===h.id)(g=h.threshold)?g=d.intersectionRatio>=g:(g=d.intersectionRect,g=0<g.top||0<g.bottom||0<g.left||0<g.right);if(g){var D=h.id;g=document.getElementById(D);var D={transport:"beacon",eventCategory:"Viewport",eventAction:"impression",eventLabel:D,nonInteraction:!0},Ma=y({},this.a.fieldsObj,z(g,this.a.attributePrefix));this.c.send("event",x(D,Ma,this.c,this.a.hitFilter,g));h.trackFirstImpressionOnly&& b.push(h)}}b.length&&this.unobserveElements(b)};f.K=function(a){var b=this,c=this.i[a]=document.getElementById(a);this.items.forEach(function(d){a==d.id&&b.h[d.threshold].observe(c)})};f.L=function(a){var b=this,c=this.i[a];this.items.forEach(function(d){a==d.id&&b.h[d.threshold].unobserve(c)});this.i[a]=null};f.remove=function(){this.unobserveAllElements()};F("impressionTracker",ya);function za(a){"string"==typeof a&&(a={id:a});return y({threshold:0,trackFirstImpressionOnly:!0},a)} function Aa(){this.a={}}function Ba(a,b){(a.a.externalSet=a.a.externalSet||[]).push(b)}Aa.prototype.ca=function(a,b){for(var c=[],d=1;d<arguments.length;++d)c[d-1]=arguments[d];(this.a[a]=this.a[a]||[]).forEach(function(a){return a.apply(null,[].concat(m(c)))})};var N={},O=!1,P;function Q(a,b){b=void 0===b?{}:b;this.a={};this.b=a;this.w=b;this.l=null}ha(Q,Aa);function R(a,b,c){a=["autotrack",a,b].join(":");N[a]||(N[a]=new Q(a,c),O||(window.addEventListener("storage",Ca),O=!0));return N[a]} function S(){if(null!=P)return P;try{window.localStorage.setItem("autotrack","autotrack"),window.localStorage.removeItem("autotrack"),P=!0}catch(a){P=!1}return P}Q.prototype.get=function(){if(this.l)return this.l;if(S())try{this.l=Da(window.localStorage.getItem(this.b))}catch(a){}return this.l=y({},this.w,this.l)};Q.prototype.set=function(a){this.l=y({},this.w,this.l,a);if(S())try{var b=JSON.stringify(this.l);window.localStorage.setItem(this.b,b)}catch(c){}}; function Ea(a){a.l={};if(S())try{window.localStorage.removeItem(a.b)}catch(b){}}Q.prototype.j=function(){delete N[this.b];Object.keys(N).length||(window.removeEventListener("storage",Ca),O=!1)};function Ca(a){var b=N[a.key];if(b){var c=y({},b.w,Da(a.oldValue));a=y({},b.w,Da(a.newValue));b.l=a;b.ca("externalSet",a,c)}}function Da(a){var b={};if(a)try{b=JSON.parse(a)}catch(c){}return b}var T={}; function U(a,b,c){this.f=a;this.timeout=b||Fa;this.timeZone=c;this.b=this.b.bind(this);v(a,"sendHitTask",this.b);try{this.c=new Intl.DateTimeFormat("en-US",{timeZone:this.timeZone})}catch(d){}this.a=R(a.get("trackingId"),"session",{hitTime:0,isExpired:!1});this.a.get().id||this.a.set({id:C()})}function Ga(a,b,c){var d=a.get("trackingId");return T[d]?T[d]:T[d]=new U(a,b,c)}function V(a){return a.a.get().id} U.prototype.isExpired=function(a){a=void 0===a?V(this):a;if(a!=V(this))return!0;a=this.a.get();if(a.isExpired)return!0;var b=a.hitTime;return b&&(a=new Date,b=new Date(b),a-b>6E4*this.timeout||this.c&&this.c.format(a)!=this.c.format(b))?!0:!1};U.prototype.b=function(a){var b=this;return function(c){a(c);var d=c.get("sessionControl");c="start"==d||b.isExpired();var d="end"==d,e=b.a.get();e.hitTime=+new Date;c&&(e.isExpired=!1,e.id=C());d&&(e.isExpired=!0);b.a.set(e)}}; U.prototype.j=function(){w(this.f,"sendHitTask",this.b);this.a.j();delete T[this.f.get("trackingId")]};var Fa=30;function W(a,b){I(a,G.W);window.addEventListener&&(this.b=y({increaseThreshold:20,sessionTimeout:Fa,fieldsObj:{}},b),this.f=a,this.c=Ha(this),this.g=ta(this.g.bind(this),500),this.o=this.o.bind(this),this.a=R(a.get("trackingId"),"plugins/max-scroll-tracker"),this.m=Ga(a,this.b.sessionTimeout,this.b.timeZone),v(a,"set",this.o),Ia(this))} function Ia(a){100>(a.a.get()[a.c]||0)&&window.addEventListener("scroll",a.g)} W.prototype.g=function(){var a=document.documentElement,b=document.body,a=Math.min(100,Math.max(0,Math.round(window.pageYOffset/(Math.max(a.offsetHeight,a.scrollHeight,b.offsetHeight,b.scrollHeight)-window.innerHeight)*100))),b=V(this.m);b!=this.a.get().sessionId&&(Ea(this.a),this.a.set({sessionId:b}));if(this.m.isExpired(this.a.get().sessionId))Ea(this.a);else if(b=this.a.get()[this.c]||0,a>b&&(100!=a&&100!=b||window.removeEventListener("scroll",this.g),b=a-b,100==a||b>=this.b.increaseThreshold)){var c= {};this.a.set((c[this.c]=a,c.sessionId=V(this.m),c));a={transport:"beacon",eventCategory:"Max Scroll",eventAction:"increase",eventValue:b,eventLabel:String(a),nonInteraction:!0};this.b.maxScrollMetricIndex&&(a["metric"+this.b.maxScrollMetricIndex]=b);this.f.send("event",x(a,this.b.fieldsObj,this.f,this.b.hitFilter))}};W.prototype.o=function(a){var b=this;return function(c,d){a(c,d);var e={};(B(c)?c:(e[c]=d,e)).page&&(c=b.c,b.c=Ha(b),b.c!=c&&Ia(b))}}; function Ha(a){a=t(a.f.get("page")||a.f.get("location"));return a.pathname+a.search}W.prototype.remove=function(){this.m.j();window.removeEventListener("scroll",this.g);w(this.f,"set",this.o)};F("maxScrollTracker",W);var Ja={};function Ka(a,b){I(a,G.X);window.matchMedia&&(this.a=y({changeTemplate:this.changeTemplate,changeTimeout:1E3,fieldsObj:{}},b),B(this.a.definitions)&&(b=this.a.definitions,this.a.definitions=Array.isArray(b)?b:[b],this.b=a,this.c=[],La(this)))} function La(a){a.a.definitions.forEach(function(b){if(b.name&&b.dimensionIndex){var c=Na(b);a.b.set("dimension"+b.dimensionIndex,c);Oa(a,b)}})}function Na(a){var b;a.items.forEach(function(a){Pa(a.media).matches&&(b=a)});return b?b.name:"(not set)"} function Oa(a,b){b.items.forEach(function(c){c=Pa(c.media);var d=ta(function(){var c=Na(b),d=a.b.get("dimension"+b.dimensionIndex);c!==d&&(a.b.set("dimension"+b.dimensionIndex,c),c={transport:"beacon",eventCategory:b.name,eventAction:"change",eventLabel:a.a.changeTemplate(d,c),nonInteraction:!0},a.b.send("event",x(c,a.a.fieldsObj,a.b,a.a.hitFilter)))},a.a.changeTimeout);c.addListener(d);a.c.push({fa:c,da:d})})}Ka.prototype.remove=function(){for(var a=0,b;b=this.c[a];a++)b.fa.removeListener(b.da)}; Ka.prototype.changeTemplate=function(a,b){return a+" \x3d\x3e "+b};F("mediaQueryTracker",Ka);function Pa(a){return Ja[a]||(Ja[a]=window.matchMedia(a))}function X(a,b){I(a,G.Y);window.addEventListener&&(this.a=y({formSelector:"form",shouldTrackOutboundForm:this.shouldTrackOutboundForm,fieldsObj:{},attributePrefix:"ga-"},b),this.b=a,this.c=p("submit",this.a.formSelector,this.f.bind(this)))} X.prototype.f=function(a,b){var c={transport:"beacon",eventCategory:"Outbound Form",eventAction:"submit",eventLabel:t(b.action).href};if(this.a.shouldTrackOutboundForm(b,t)){navigator.sendBeacon||(a.preventDefault(),c.hitCallback=ua(function(){b.submit()}));var d=y({},this.a.fieldsObj,z(b,this.a.attributePrefix));this.b.send("event",x(c,d,this.b,this.a.hitFilter,b,a))}}; X.prototype.shouldTrackOutboundForm=function(a,b){a=b(a.action);return a.hostname!=location.hostname&&"http"==a.protocol.slice(0,4)};X.prototype.remove=function(){this.c.j()};F("outboundFormTracker",X); function Y(a,b){var c=this;I(a,G.Z);window.addEventListener&&(this.a=y({events:["click"],linkSelector:"a, area",shouldTrackOutboundLink:this.shouldTrackOutboundLink,fieldsObj:{},attributePrefix:"ga-"},b),this.f=a,this.c=this.c.bind(this),this.b={},this.a.events.forEach(function(a){c.b[a]=p(a,c.a.linkSelector,c.c)}))} Y.prototype.c=function(a,b){if(this.a.shouldTrackOutboundLink(b,t)){var c=b.getAttribute("href")||b.getAttribute("xlink:href"),d=t(c),e={transport:"beacon",eventCategory:"Outbound Link",eventAction:a.type,eventLabel:d.href};navigator.sendBeacon||"click"!=a.type||"_blank"==b.target||a.metaKey||a.ctrlKey||a.shiftKey||a.altKey||1<a.which||window.addEventListener("click",function(a){a.defaultPrevented||(a.preventDefault(),e.hitCallback=ua(function(){location.href=c}))});d=y({},this.a.fieldsObj,z(b,this.a.attributePrefix)); this.f.send("event",x(e,d,this.f,this.a.hitFilter,b,a))}};Y.prototype.shouldTrackOutboundLink=function(a,b){a=a.getAttribute("href")||a.getAttribute("xlink:href");b=b(a);return b.hostname!=location.hostname&&"http"==b.protocol.slice(0,4)};Y.prototype.remove=function(){var a=this;Object.keys(this.b).forEach(function(b){a.b[b].j()})};F("outboundLinkTracker",Y);var Z=C(); function Qa(a,b){var c=this;I(a,G.$);document.visibilityState&&(this.a=y({sessionTimeout:Fa,visibleThreshold:5E3,sendInitialPageview:!1,fieldsObj:{}},b),this.b=a,this.g=document.visibilityState,this.m=null,this.o=!1,this.v=this.v.bind(this),this.s=this.s.bind(this),this.G=this.G.bind(this),this.N=this.N.bind(this),this.c=R(a.get("trackingId"),"plugins/page-visibility-tracker"),Ba(this.c,this.N),this.f=Ga(a,this.a.sessionTimeout,this.a.timeZone),v(a,"set",this.v),window.addEventListener("unload",this.G), document.addEventListener("visibilitychange",this.s),va(this.b,function(){if("visible"==document.visibilityState)c.a.sendInitialPageview&&(Ra(c,{ea:!0}),c.o=!0),c.c.set({time:+new Date,state:"visible",pageId:Z,sessionId:V(c.f)});else if(c.a.sendInitialPageview&&c.a.pageLoadsMetricIndex){var a={},a=(a.transport="beacon",a.eventCategory="Page Visibility",a.eventAction="page load",a.eventLabel="(not set)",a["metric"+c.a.pageLoadsMetricIndex]=1,a.nonInteraction=!0,a);c.b.send("event",x(a,c.a.fieldsObj, c.b,c.a.hitFilter))}}))}f=Qa.prototype; f.s=function(){var a=this;if("visible"==document.visibilityState||"hidden"==document.visibilityState){var b=Sa(this),c={time:+new Date,state:document.visibilityState,pageId:Z,sessionId:V(this.f)};"visible"==document.visibilityState&&this.a.sendInitialPageview&&!this.o&&(Ra(this),this.o=!0);"hidden"==document.visibilityState&&this.m&&clearTimeout(this.m);this.f.isExpired(b.sessionId)?(Ea(this.c),"hidden"==this.g&&"visible"==document.visibilityState&&(clearTimeout(this.m),this.m=setTimeout(function(){a.c.set(c); Ra(a,{hitTime:c.time})},this.a.visibleThreshold))):(b.pageId==Z&&"visible"==b.state&&Ta(this,b),this.c.set(c));this.g=document.visibilityState}};function Sa(a){var b=a.c.get();"visible"==a.g&&"hidden"==b.state&&b.pageId!=Z&&(b.state="visible",b.pageId=Z,a.c.set(b));return b} function Ta(a,b,c){c=(c?c:{}).hitTime;var d={hitTime:c},d=(d?d:{}).hitTime;(b=b.time?(d||+new Date)-b.time:0)&&b>=a.a.visibleThreshold&&(b=Math.round(b/1E3),d={transport:"beacon",nonInteraction:!0,eventCategory:"Page Visibility",eventAction:"track",eventValue:b,eventLabel:"(not set)"},c&&(d.queueTime=+new Date-c),a.a.visibleMetricIndex&&(d["metric"+a.a.visibleMetricIndex]=b),a.b.send("event",x(d,a.a.fieldsObj,a.b,a.a.hitFilter)))} function Ra(a,b){var c=b?b:{};b=c.hitTime;var c=c.ea,d={transport:"beacon"};b&&(d.queueTime=+new Date-b);c&&a.a.pageLoadsMetricIndex&&(d["metric"+a.a.pageLoadsMetricIndex]=1);a.b.send("pageview",x(d,a.a.fieldsObj,a.b,a.a.hitFilter))}f.v=function(a){var b=this;return function(c,d){var e={},e=B(c)?c:(e[c]=d,e);e.page&&e.page!==b.b.get("page")&&"visible"==b.g&&b.s();a(c,d)}};f.N=function(a,b){a.time!=b.time&&(b.pageId!=Z||"visible"!=b.state||this.f.isExpired(b.sessionId)||Ta(this,b,{hitTime:a.time}))}; f.G=function(){"hidden"!=this.g&&this.s()};f.remove=function(){this.c.j();this.f.j();w(this.b,"set",this.v);window.removeEventListener("unload",this.G);document.removeEventListener("visibilitychange",this.s)};F("pageVisibilityTracker",Qa); function Ua(a,b){I(a,G.aa);window.addEventListener&&(this.a=y({fieldsObj:{},hitFilter:null},b),this.b=a,this.u=this.u.bind(this),this.J=this.J.bind(this),this.D=this.D.bind(this),this.A=this.A.bind(this),this.B=this.B.bind(this),this.F=this.F.bind(this),"complete"!=document.readyState?window.addEventListener("load",this.u):this.u())}f=Ua.prototype; f.u=function(){if(window.FB)try{window.FB.Event.subscribe("edge.create",this.B),window.FB.Event.subscribe("edge.remove",this.F)}catch(a){}window.twttr&&this.J()};f.J=function(){var a=this;try{window.twttr.ready(function(){window.twttr.events.bind("tweet",a.D);window.twttr.events.bind("follow",a.A)})}catch(b){}};function Va(a){try{window.twttr.ready(function(){window.twttr.events.unbind("tweet",a.D);window.twttr.events.unbind("follow",a.A)})}catch(b){}} f.D=function(a){if("tweet"==a.region){var b={transport:"beacon",socialNetwork:"Twitter",socialAction:"tweet",socialTarget:a.data.url||a.target.getAttribute("data-url")||location.href};this.b.send("social",x(b,this.a.fieldsObj,this.b,this.a.hitFilter,a.target,a))}}; f.A=function(a){if("follow"==a.region){var b={transport:"beacon",socialNetwork:"Twitter",socialAction:"follow",socialTarget:a.data.screen_name||a.target.getAttribute("data-screen-name")};this.b.send("social",x(b,this.a.fieldsObj,this.b,this.a.hitFilter,a.target,a))}};f.B=function(a){this.b.send("social",x({transport:"beacon",socialNetwork:"Facebook",socialAction:"like",socialTarget:a},this.a.fieldsObj,this.b,this.a.hitFilter))}; f.F=function(a){this.b.send("social",x({transport:"beacon",socialNetwork:"Facebook",socialAction:"unlike",socialTarget:a},this.a.fieldsObj,this.b,this.a.hitFilter))};f.remove=function(){window.removeEventListener("load",this.u);try{window.FB.Event.unsubscribe("edge.create",this.B),window.FB.Event.unsubscribe("edge.remove",this.F)}catch(a){}Va(this)};F("socialWidgetTracker",Ua); function Wa(a,b){I(a,G.ba);history.pushState&&window.addEventListener&&(this.a=y({shouldTrackUrlChange:this.shouldTrackUrlChange,trackReplaceState:!1,fieldsObj:{},hitFilter:null},b),this.b=a,this.c=location.pathname+location.search,this.H=this.H.bind(this),this.I=this.I.bind(this),this.C=this.C.bind(this),v(history,"pushState",this.H),v(history,"replaceState",this.I),window.addEventListener("popstate",this.C))}f=Wa.prototype; f.H=function(a){var b=this;return function(c){for(var d=[],e=0;e<arguments.length;++e)d[e-0]=arguments[e];a.apply(null,[].concat(m(d)));Xa(b,!0)}};f.I=function(a){var b=this;return function(c){for(var d=[],e=0;e<arguments.length;++e)d[e-0]=arguments[e];a.apply(null,[].concat(m(d)));Xa(b,!1)}};f.C=function(){Xa(this,!0)}; function Xa(a,b){setTimeout(function(){var c=a.c,d=location.pathname+location.search;c!=d&&a.a.shouldTrackUrlChange.call(a,d,c)&&(a.c=d,a.b.set({page:d,title:document.title}),(b||a.a.trackReplaceState)&&a.b.send("pageview",x({transport:"beacon"},a.a.fieldsObj,a.b,a.a.hitFilter)))},0)}f.shouldTrackUrlChange=function(a,b){return!(!a||!b)};f.remove=function(){w(history,"pushState",this.H);w(history,"replaceState",this.I);window.removeEventListener("popstate",this.C)};F("urlChangeTracker",Wa);})(); //# sourceMappingURL=autotrack.js.map ga('blogger.require', 'outboundLinkTracker'); //]]> </script> <script type="text/javascript" src="https://www.blogger.com/static/v1/widgets/2263754362-widgets.js"></script> <script type='text/javascript'> window['__wavt'] = 'AOuZoY4RHignTftOb_-TpSmZ9Ji_r8wKUQ:1733255887681';_WidgetManager._Init('//www.blogger.com/rearrange?blogID\x3d8698702854482141883','//opensource.googleblog.com/2020/08/','8698702854482141883'); _WidgetManager._SetDataContext([{'name': 'blog', 'data': {'blogId': '8698702854482141883', 'title': 'Google Open Source Blog', 'url': 'https://opensource.googleblog.com/2020/08/', 'canonicalUrl': 'https://opensource.googleblog.com/2020/08/', 'homepageUrl': 'https://opensource.googleblog.com/', 'searchUrl': 'https://opensource.googleblog.com/search', 'canonicalHomepageUrl': 'https://opensource.googleblog.com/', 'blogspotFaviconUrl': 'https://opensource.googleblog.com/favicon.ico', 'bloggerUrl': 'https://www.blogger.com', 'hasCustomDomain': true, 'httpsEnabled': true, 'enabledCommentProfileImages': false, 'gPlusViewType': 'FILTERED_POSTMOD', 'adultContent': false, 'analyticsAccountNumber': 'UA-53341410-4', 'encoding': 'UTF-8', 'locale': 'en', 'localeUnderscoreDelimited': 'en', 'languageDirection': 'ltr', 'isPrivate': false, 'isMobile': false, 'isMobileRequest': false, 'mobileClass': '', 'isPrivateBlog': false, 'isDynamicViewsAvailable': true, 'feedLinks': '\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22Google Open Source Blog - Atom\x22 href\x3d\x22https://opensource.googleblog.com/feeds/posts/default\x22 /\x3e\n\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/rss+xml\x22 title\x3d\x22Google Open Source Blog - RSS\x22 href\x3d\x22https://opensource.googleblog.com/feeds/posts/default?alt\x3drss\x22 /\x3e\n\x3clink rel\x3d\x22service.post\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22Google Open Source Blog - Atom\x22 href\x3d\x22https://www.blogger.com/feeds/8698702854482141883/posts/default\x22 /\x3e\n', 'meTag': '', 'adsenseHostId': 'ca-host-pub-1556223355139109', 'adsenseHasAds': false, 'adsenseAutoAds': false, 'boqCommentIframeForm': true, 'loginRedirectParam': '', 'view': '', 'dynamicViewsCommentsSrc': '//www.blogblog.com/dynamicviews/4224c15c4e7c9321/js/comments.js', 'dynamicViewsScriptSrc': '//www.blogblog.com/dynamicviews/0399bd29ab1434ad', 'plusOneApiSrc': 'https://apis.google.com/js/platform.js', 'disableGComments': true, 'interstitialAccepted': false, 'sharing': {'platforms': [{'name': 'Get link', 'key': 'link', 'shareMessage': 'Get link', 'target': ''}, {'name': 'Facebook', 'key': 'facebook', 'shareMessage': 'Share to Facebook', 'target': 'facebook'}, {'name': 'BlogThis!', 'key': 'blogThis', 'shareMessage': 'BlogThis!', 'target': 'blog'}, {'name': 'X', 'key': 'twitter', 'shareMessage': 'Share to X', 'target': 'twitter'}, {'name': 'Pinterest', 'key': 'pinterest', 'shareMessage': 'Share to Pinterest', 'target': 'pinterest'}, {'name': 'Email', 'key': 'email', 'shareMessage': 'Email', 'target': 'email'}], 'disableGooglePlus': true, 'googlePlusShareButtonWidth': 0, 'googlePlusBootstrap': '\x3cscript type\x3d\x22text/javascript\x22\x3ewindow.___gcfg \x3d {\x27lang\x27: \x27en\x27};\x3c/script\x3e'}, 'hasCustomJumpLinkMessage': false, 'jumpLinkMessage': 'Read more', 'pageType': 'archive', 'pageName': 'August 2020', 'pageTitle': 'Google Open Source Blog: August 2020', 'metaDescription': ''}}, {'name': 'features', 'data': {}}, {'name': 'messages', 'data': {'edit': 'Edit', 'linkCopiedToClipboard': 'Link copied to clipboard!', 'ok': 'Ok', 'postLink': 'Post Link'}}, {'name': 'template', 'data': {'name': 'custom', 'localizedName': 'Custom', 'isResponsive': false, 'isAlternateRendering': false, 'isCustom': true}}, {'name': 'view', 'data': {'classic': {'name': 'classic', 'url': '?view\x3dclassic'}, 'flipcard': {'name': 'flipcard', 'url': '?view\x3dflipcard'}, 'magazine': {'name': 'magazine', 'url': '?view\x3dmagazine'}, 'mosaic': {'name': 'mosaic', 'url': '?view\x3dmosaic'}, 'sidebar': {'name': 'sidebar', 'url': '?view\x3dsidebar'}, 'snapshot': {'name': 'snapshot', 'url': '?view\x3dsnapshot'}, 'timeslide': {'name': 'timeslide', 'url': '?view\x3dtimeslide'}, 'isMobile': false, 'title': 'Google Open Source Blog', 'description': '', 'url': 'https://opensource.googleblog.com/2020/08/', 'type': 'feed', 'isSingleItem': false, 'isMultipleItems': true, 'isError': false, 'isPage': false, 'isPost': false, 'isHomepage': false, 'isArchive': true, 'isLabelSearch': false, 'archive': {'year': 2020, 'month': 8, 'rangeMessage': 'Showing posts from August, 2020'}}}]); _WidgetManager._RegisterWidget('_HeaderView', new _WidgetInfo('Header1', 'header', document.getElementById('Header1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogView', new _WidgetInfo('Blog1', 'main', document.getElementById('Blog1'), {'cmtInteractionsEnabled': false}, 'displayModeFull')); _WidgetManager._RegisterWidget('_HTMLView', new _WidgetInfo('HTML4', 'sidebar-right-1', document.getElementById('HTML4'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_PopularPostsView', new _WidgetInfo('PopularPosts1', 'sidebar-right-1', document.getElementById('PopularPosts1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogArchiveView', new _WidgetInfo('BlogArchive1', 'sidebar-right-1', document.getElementById('BlogArchive1'), {'languageDirection': 'ltr', 'loadingMessage': 'Loading\x26hellip;'}, 'displayModeFull')); _WidgetManager._RegisterWidget('_HTMLView', new _WidgetInfo('HTML3', 'sidebar-right-1', document.getElementById('HTML3'), {}, 'displayModeFull')); </script> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10