 Thank you for coming, sorry for starting a little bit late. The last time I gave this talk it ran about an hour and we've got like 25 minutes left. So hopefully it will be okay. I've squished it a bit but I added some more too. So thank you again for coming. This is Google Cloud Platform Loves Ruby because we do. And of course you're here in the sponsor track so this talk is brought to you by Google Cloud Platform. The most favoritist, wonderfulist Cloud Platform according to Remy, four out of five Remy is a pro. I don't know about that other Remy. So hi, I'm Remy Taylor. I'm a developer programs engineer. I work in DevRel for Google Cloud. And if you didn't guess, I'm of Ruby S. And fun fact, I'm also from Phoenix. Is anyone of Phoenix Rubyist here? I'm just curious, no, a couple, yay. Okay, I did my first Rails app here. I did my first lots of things. So it's really good to see you guys. So this is a sponsor talk. I appreciated when I looked at this that I put in the program. I put Ruby developers welcome in my RailsConf talk. Maybe because I've reused this abstract but Ruby developers are definitely welcome. What we're gonna talk about though is this. So we've put together a dedicated team of Rubyists at Google Cloud. A lot of people are surprised to hear that we have a Ruby team but we do and it's been growing for the past two years. We've brought together a diverse set of engineers of all different kinds, product managers and our goal or mandate if you will is to make the experience for Rubyist on Google Cloud as best as possible. We use the Cloud all the time. We call our APIs for Google Cloud. We deploy our Ruby code. And so we feel any of the friction and we try and work to make that the best possible. And what that's been looking like is we've been building a number of things. So that includes Ruby libraries. We're gonna spend a lot of the first part of this talk on looking at those. App Engine, which is one of the many places you can deploy your Ruby code to and debugging. So once you take your Ruby code and you've got it up and running, how do you maintain it after that? If there's one takeaway that I'd like you guys to leave with today, it's cloud.google.com slash ruby. You'll actually see this printed on the back of our t-shirts if you check out our GCP booth, which I highly recommend. There's a bunch of us. Please feel to inundate us with all of your questions. And we've been putting together articles and resources on this site to help people get started. So it's a good jumping off point and we continue to add more information there. So today, what I'm gonna walk through is libraries. I'm gonna spend a bunch of time there because it's one of my favorite things we've been working on. Runtimes to get your application up and running and debugging. So first let's look at some libraries. Google Cloud has a lot of products. I didn't fit them all here on the screen. This just fit with my OCD and looked good. And a lot of these products have really powerful APIs. So as a Rubyist, I want it to be as easy as possible for me to call out to those APIs. So for Ruby, we've put together a number of client libraries. I don't know if you can see which ones were highlighted here on the projector, but there's about 15 of these that I highlighted that today we have Ruby client libraries for that you can go and use. And please do and give us feedback. So what does it look like to use one of these? Let me get you started. We're Rubyists, so if you tell us to use an API, we're probably going to look for a gem. So we're going to, let's try Google Cloud Storage, which is one of our products. It's kind of a file object store. So for that, we'll install Google Cloud Storage for a lot of our other Google Cloud products. You'd install Google Cloud Vision or speech and so on. So pretty obvious. Oh no, don't show the cat yet. So let me show you what we're going to do with our little code sample to get up and running. What I have open here, if you haven't been to our platform, is the Google Cloud Console. If you're using Google Cloud, you'll live there a lot. Here I have the storage browser open. So in Cloud Storage, we manage our files into buckets of buckets and here we're browsing one of them called my cat pictures. If you can see, it says there are no objects in this bucket, which is very sad. So what we will do is fix that right now. Presuming you have the Google Cloud Storage gem installed or in your gem file, what your Ruby code will look like to have this cat is we're gonna require Google Cloud Storage, just like the gem, pretty simple. And then we want some kind of a service object to make our calls out to the API, right? So we'll make a storage object and that is a Google Cloud Storage. Hopefully you're noticing a pattern here. For the bucket, we need some kind of representation of that to be able to say add a file to that bucket. So we get a bucket object here and then to add the file, you can just say bucket new file. And assuming you have my cat ping, then that'll work. Which kind of interesting, I mean it's very cool. Part of what I wanna show to you guys today is what makes me passionate are idioms, right? So we're Rubyists and if you don't wanna call a new file because you don't like the name and the method, you don't have to. Maybe you want to create the file or upload the file. For anyone who happened to see DHH's keynote yesterday, a lot of what he talked about were kind of the belief systems of Ruby. And for example, we don't necessarily like there to be one way to do something. We love aliases and we are Rubyists who made these client libraries. So you'll see a lot of those Ruby idioms in there because we made them, we wanna use these. So another thing for example is if you don't wanna pass a file string like a path to it, you can pass a Ruby file object and we actually just treat that as an IO which is a very Ruby-ish thing to do. So if you want, you can pass a string IO which if you're not familiar is kind of a way to take a string and fake it and say, here's an IO, treat this as a file. So those are the kinds of very Ruby-ish things that we do. Once we've done that, we get our My Cat and the world is a great place again. It'd be better if it were a dog. I don't know why I use cats. So I want to point you to a couple of places where you can get up and running with these and find some of the reference docs, et cetera. So all of our client libraries are of course open source up on GitHub. They're in our Google Cloud platform organization. So all the Ruby libraries are in the Google Cloud Ruby repository. I know what you guys are asking and the answer is yes, we are accepting contributions. Please send us your pull requests or file issues. We love hearing feedback and actually number the issues. Even recently, I can think of some that have been filed. We've directly pretty much immediately made changes to some of our APIs when possible and made the developer experience as good as possible. Those IOs were a recent one we did with storage. When you go to GitHub, click our website. This is our website on GitHub for all of the client libraries. I spend a lot of my day job using these client libraries, giving feedback on them, making samples for them. We've got new ones coming out all the time and for some of the younger ones, the APIs are changing for them all the time while we iterate on making them amazing. So I live in this website and I'm actually really proud of it. It's really fun. I feel like once you get up and running and you're like, okay, now I need to know the method references because now I need to do something real with this, I think you'll find yourself pleased here. We're not missing any docs. And then similarly, if you're coming from the product side of things, you know that you wanna use Google Cloud Vision to upload images and have our artificial and machine learning system say, hey, there's Doug and the Eiffel Tower in this image. Pull up that product page. For most of our product pages, and it is really exciting, I'm giving a talk about docs, right? But honestly, they're really cool because for most of our products, we have this client libraries page, which for Ruby will tell you everything you need to know in one small page, what gem, including how to authenticate. The first time you call out to the APIs, you're going to install a tool and set up authentication. You'll do it once, but that's here on every page and there's code snippets and links to references that link out to places like that GitHub page. Cool, so you're pretty educated. Now you've got good places to go. And one thing I like about these client libraries is we try and follow all the same idioms and conventions amongst all of them. So when you learn one, it should be really easy for you to switch to any other. Let me just give you a couple examples. Here's an example of using storage again. So just a reminder, we require storage, we make a client, we make a bucket in this case for storage. And here in this case, we're just looping through the files in the bucket. Pretty enigmatic, pretty much what you would expect. Here's a completely different product. I don't know if you guys noticed that I switched the slide, but this is our NoSQL database solution, Datastore. Here, we're making a service for Datastore and here we're making a query, running the query and looping over the results. In this case, printing out the names of dogs. Pretty simple, pretty similar. Completely different product. This time we're managing DNS entries. Here, we grab a zone from the DNS service and print out the records. Super simple, these look almost identical. Here's our PubSub product. We grab a subscription. Whenever you publish messages to a topic, those get fanned out to subscriptions. So a common use case is for a given subscription. You may want it to kind of block and just listen and kind of hang out and be like, I'm gonna process this, I'm gonna process this. Like we use it for background jobs, for example. So here's a nice little teeny idiomatic method. Listen to the subscription and it will process every message. Couple more, just cause. Here's one of the machine learning ones. Definitely go and play with our machine learning APIs. And one of my coworkers will be talking about natural language processing leader today. And here, we're doing something a little bit more complicated. We're taking one sentence, but it could be a whole document. And the language API is getting called and for every sentence in that document, it gives you the sentiment of it. Really simple, really powerful, right? So here's another thing that the code looks trivial in my opinion. Upload an audio file. Upload like a wave file. And this prints the text that our speech API detects in your audio file. So what was said? As easy, upload an image. And in this case, if you upload an image of your dog, labels would be things like dog, golden retriever, mammal, any of the things it notices there. Or also for vision, almost the same exact thing, let's print out the landmarks and print out the lat long. So I love that these are so simple and any amount of care print out the faces. They're just about the same. They are easy as pie. Horrible, horrible joke. So besides being really easy, one of my favorite things about using these and working on building them and making the great developer experience is how ruby-ish they are. For our data store, you saw a small query, but here is a bigger one. Y'all have probably seen something like this. This looks like a lot of our libraries that we use for interacting with SQL or NoSQL like document stores. Should feel pretty familiar, and that's one of our goals. Here was that cool little method that I love. This is one of my favorites. There's a lot of code on this slide, but I would wager that anyone who knows DNS, even if you're not a programmer, I think you'd be able to figure out exactly what's happening here. So this is a cool example of a DSL of ours. So this happens to do all this in a transaction, but if you know DNS, we're adding an A record for www2NIP. We're changing some MX records, changing the TTL on one CNAME. I love this one. I'll wait for you to take a picture with your phone. I'll make sure these are available later. And there are other cool things we do like when we started using our logging product, we realized all of our actual Rails applications and our other applications, they use a normal Ruby logger. So we started using a logging product and we had to call these custom API methods and we were like, no, this is stupid. Why don't we have our logging client library just give you a logger? It just gives you a standard Ruby logger and you can put it in your Rails apps or wherever you would normally expect to. So this is just another cool example of something that you get when a bunch of Rubyists hang out and use these products, feel the friction and it's coming from us. This isn't Java written in Ruby, which I know some of us have seen. And finally I wanna end on this. BigQuery has data sets with tables. At RailsConf, I'm sure all of you are very familiar with the syntax. So it looks a whole lot like an active record migration. This is the syntax for our migrations for updating or adding BigQuery schema. So based off of tons of idioms like that used in active record and SQL. Okay, yay, educated. While I watch the time, let's click through a couple of just like refreshers for how you can file up on this when you get back to your hotel and you wanna start playing with this. So of course cloud.google.com slash Ruby. It's a great jumping off point, but especially for the libraries, going to GitHub, opening up that website that we have on GitHub with all the references is a great place to get started. I love these and similarly for the product docs. Not only do we have these cool client library pages, but for a lot of products we have really simple little lists of how to guides. So I showed you how to do landmarks. Here's how to get some of the text from an image or the landmarks or some faces. They're really simple little snippets. It looks really simple. It looks like not a lot of work went into them. We put a lot of work into them to make them that simple. So that is really easy and all of these are copy-pastable, which is wonderful. And these client library pages exist for a lot of our products and you'll notice it's not just for Ruby. We've gotten most of these six other languages that you can use in case you've got other languages at your businesses. Cool, so let's jump into some run times and get up and running. So I want to, with the little time we have, stop and tell a really short story. I want to go back in time. I want to go back to 2009. 2009 was a really cool year for Ruby and for Rails. For Ruby, Ruby 191 had just been released. This is important because this was the first stable version of the 19 series. That brought us YARV, the new bytecode interpreter. It brought us a lot of syntax that we're familiar with today, like the new hash syntax, the arrow syntax for lambdas and a lot of other important things came from this. Also, Rails 2.3. This was one of the, maybe I was most excited about this Rails release than any sense and that's because this updated Rails to be fully based on top of Rack. Before that, it hadn't been when Rack was created, kind of shoehorned it in. This updated everything to be fully based on it and it gave us as a side effect things like Rails engines and metal. And just for a brief context for the time period we're in, we probably use Bundler today. Bundler integration for Rails wasn't a thing yet. So that's cute. We went back in time eight years, but why do I care? I care because in 2009, in Phoenix, I gave my very first talk about running Ruby on App Engine. Of course, App Engine was Java then, so I used JRuby, but these are some of my old slides, I've remastered them a little, but this is my old slide from Desert Code Camp in 2009. And it's interesting, I spent a lot of time getting my Ruby running on App Engine and you might think, why? I mean, this was kind of an uphill battle. Why am I trying to run my Ruby in an environment that totally wasn't made for it? We weren't the target audience. When I answered it in my old slides, and the answer here was just magic, pure magic. Here was one of the quotes from the App Engine website at that time. It says, App Engine uses multiple web servers to run your application and automatically adjust the number of servers it's using to handle requests reliably. In 2009, that was amazing, that was a dream come true. I mean, at the time, most of my deployment was kind of this rat's nest of wires basically managed and hacked together with the Scotch tape that is Capistrano. And don't get me wrong, I was really proud of my Capistrano scripts, but I would prefer the magic, I would prefer to not have had those. So that's why we use those then, and I wasn't the only one asking for it. So back when App Engine was released, the 29th issue filed on the issue tracker. Here in 2008, year before, was for RubySport and the request kept coming in. So now, nine years later for that, in 2017, on Google Cloud, we have a much better story for Ruby and we have a lot of different options. So today, if you want full control, you can use Compute Engine. This will give you full virtual machines and you can manage them how you like with the reload balance or et cetera, et cetera. If you're already using containers and Docker, you may be interested in using Google Container Engine. This is essentially Google's hosted version of Kubernetes. And then of course, what I want to briefly look at is App Engine. I'm an app developer, so this is kind of the model for me. I want to give Google my application and say go. Like I'm an app developer, I'm gonna update this and send changes, but just please keep it working. So the new App Engine, App Engine flexible environment, runs a lot of different languages and we GA the whole product, including the Ruby run time this year. So you can use them, we will support you. And for the Ruby run time, a benefit is we still get all that magic. So now today, many years later, I can run my Ruby on App Engine and still get that scaling, still get a wonderful experience where I just give it my application. How's it work? Short answer, let me check our time, is cloud.google.com slash ruby slash rails. It's a good place to get up and running. We also have our Container Engine, Compute Engine tutorials here, but this has a page that'll just walk you through the requirements. Get you up and running with Google Cloud if you haven't already. The TLDR for this, if you want to click, click, click, is, you need a Google account, okay, duh. You need to log into Google Cloud Console. Cool, go ahead and do that. You're in there and make a project. Google Cloud projects are what most of our resources are associated with, a storage bucket and is part of a project. App Engine applications are associated with a project. After that, install the Google Cloud SDK at cloud.google.com slash SDK. This gives you the GCloud command line tool as well as a couple of others that are really powerful and it's what we use to interact with all of our cloud products. So if you want to do orchestration, if you want to, from the command line as opposed to our UI, make a bunch of SQL instances, Postgres instances, whatever it may be, that's where you can do it. Once you've got it, CD into your app. This could be Rails app, could be a Sinatra app, a rack app, whatever, run GCloud, app deploy and it knows what to do. It's like, hey, this is a Ruby application. I know what to do with this. The only thing we give you a prompt for is how do you want to boot it? We currently use rack up here so this will just work for Rails, hit enter. But you could also say bundle exec mysinatraapp.rb or whatever you would want to do. Wait a few seconds, maybe a little bit more and then your app is deployed. Hooray, fantastic. But for here, what I'm interested in is those cool Rubyisms that we've put into this, the love. Once you've actually deployed your application and you really start to use it, what do you need? What are the pain points and the friction that we've been working on? One of the first things you'll probably need in the real world is to specify the Ruby version. So how do we do that? Well, we didn't reinvent the wheel. We use the idioms of the community when they're there so use a Ruby version file. If you're not familiar with these, this is the file used by RBM or RVM, these idiomatic tools, which are version managers to manage a version for Ruby and associate with a given project. Of course, you can just make the file by hand too. You just put like two for one in it. But that's a good example of something that just works that we use from the community. Another pain point that came up right away, installing gems. We've got your Noko Geary, but also, anybody who's deployed to remote VMs and things a lot with Ruby maybe feels a little bit of pain associated with at least one of these gems up here. Most of these require some kind of native dependency. They could hurt you on your Mac, but as easily as well. So these usually require some kind of app package or something like that when you deploy them. So to take away that pain, what we did was, we're like, forget this. We were just going in and every time we found an error, we were like, we'll fix that and add the dependency. No, we just went to RubyGems and we got the top 1,000 most downloaded gems off of RubyGems and we just made sure they all install. So the top 1,000 most downloaded RubyGems totally install and build properly on our runtime. Done, make it work. Okay, what if you do want to install some really custom thing that no one else in the Ruby community would be using? You want to install Cowsay? Seriously, even the cow thinks that's ridiculous, but sure, we got you covered. Can do. As opposed to running gcloud app deploy, you can run gcloud app genconfig custom. It's a little bit of mouthful, but it's pretty easy. And what this does is it'll spit out a Docker file in your directory. So behind the scenes when you gcloud app deploy, we make a Docker file. It's based on our base Docker image, but we also can look at your directory and be like, oh, here's the entry point. We want to give some recommendations. Instead of making the Docker file behind scenes and deploying, what this command does is it just makes the same Docker file and it spits it out. And then the next time you deploy, your deployment won't use the bare Ruby runtime. It'll use this. So you can edit this to your heart's content. Add whatever app get packages or whatever you want, some demons in the background, whatever. App Engine Flex is really based on Docker. And there's other benefits that come with this. So when you want to take your application and take it off of App Engine, maybe you're ready to put it into a bunch of containers on Container Engine or Kubernetes. You can take our same Docker runtime and those work fine there. Okay, rushing a little bit, a little fine. So to follow up here, when you start using it and after you've gotten your hello world deployed and you're ready to start focusing on answering some of your real problems that you're having in production, go ahead and look up the docs for the Ruby runtime. And this has everything I just mentioned here. How to set a particular Ruby version, how to make a custom Docker file, but also what if you need to SSH into a container running on one of the machines? This will help you out in case you really need to do that. What if you need something like a cron job? It also has walkthroughs for connecting your App Engine instance to a fully managed Postgres or MySQL instance. A lot of those things that come up after your application is up, how do you split the traffic between multiple versions and things like that? This will answer that for you. Okay, we're running on time, but we will run through this next section on debugging. Once you've got your app like up and running, you're very happy, but what happens when that first issue happens? What happens when things start to not go so well? For example, your clients all start calling and they see this glorious page. It's all of our favorite page in the whole wide world. What do you do? So there's two things. One, and this kind of will point you in the right direction. What do you do? What do you do there? We're going to look at some of our products that'll help you through this. This is our Stackdriver suite of tools for logging, air reporting, debugging, which is very cool, and latency tracing. Looking at logging, one just quick note is after you do your GCLAD app deploy, I didn't scroll down to the bottom of the output. It'll point out that as soon as you deploy, you can from GCLAD tail your logs. I pointed out because not a lot of people spot it and I use it all the time. Tail my logs, grab to something, and watch for those exceptions or something. But for the most part, you're probably going to be in our UI. So in the Google Cloud console, search for or click on the nav logging and you'll find yourself in a screen like this. With a lot of kind of busy logs, but there's a lot of things that your applications log and I want to point your attention to this. By default, these are just some of the things that we log by default for your applications. So standard out and standard error, a benefit of this is in your Snotra app, your Rails app, your whatever, puts hello, will totally show up in the logs. So that'll get ingested and you can search for that later. Of course, you can make a logger based on standard out as well. So you can use a logger and for Rails, lo and behold, there's an environment variable that you can set that will pre-configure its logger. So Rails logger will go to standard out and that's kind of a minimal way to get up and running with logging that works and it's just useful in Elm. So here, if we deployed that, we'd be able to find our standard out. Hello, it's really busy with a lot of other requests but there's full text search so you can drill down and find those too. When exceptions happen, if you're set up in the same way, similarly, those would get logged to the standard out and you'd be able to find it. This, you can't see the stack trace, it's kind of not the best scenario, it's not the best way to do your air reporting. So now that we have Cowsay installed, he's there a better way and they're most certainly it's Jim Stackdriver. This is one of my favorite things that we've been working on for the past couple of quarters, what a corporate thing. To get up and running with it, there are two things to know. One, this is big gotcha, I still messed this up. To turn on the Stackdriver integration for one of your projects, you can opt into which one of the tools you want. So on the project side, you have to enable these APIs. Most of them are enabled by default but I know air reporting isn't, which is kind of good. You may not want the whole air reporting system turned on in our console and start getting notifications unless you want to opt into it but turn those on and then in your app throw Jim Stackdriver into your gem file, bundle, redeploy. Once you've done that, everything should just work and note all you needed was Jim Stackdriver and this will work when you deploy to a flex environment but you can also configure applications if you want to log and send air reports to Stackdriver from your machine or your other clouds and things like that. So in this case, with the gem installed, now our errors are much more pretty. You notice the severity comes through, which it didn't before and for errors, if we blow up, this is more complicated than it needed to be but I use this for debugging. If the request is invalid and we explode, we hit the read, we hit it, which is good in this case because we wanted it to explode. It's like a test of an environment. One of my favorite things is after an error occurs and you've done your gem Stackdriver and I go and I wanna go and pull up the air reporting section of the cloud console, when you go to the cloud console, like you don't even have to get that far. Our dashboard has all these cards when you log into the console and as soon as an error pops up, you'll get this card and it's like you had 37 of these runtime exceptions. Sure, I would love to click into air reporting. This is a test project so I only have one type of exception. You may have more. But this gives you a list of all your different types of exceptions. You can click into one, get all the details, the occurrences, the normal things you would expect as well as getting the stack trace, which is what we want. There's one really interesting thing about this page. You notice that these are links? There's some magic here and I put dragons on the screen intentionally because we've got this alpha. Please kick the tires on this. We're still playing around with this. But if you click one of those puppies, it'll take you to Stackdriver Debug. And now here by default, it says it couldn't find the file and you need to set up some source code, but that's okay. Right now Debugger isn't part of that Stackdriver gem. So right now you have to install it as a separate thing for now. So if you want to play around with Debugger and please do, add Google Cloud Debugger to your gem file and then require in like your App Engine, your Rails, sorry, application RB, Google Cloud Debugger Rails. This kind of loads the rail tie. Stackdriver has, our gem has a rail tie, but it also has middleware. You can use in Snotcher or your rack apps or whatever. Redeploy and then when you click the link, you'll find yourself in a really pretty debugger that I wish I wanted to spend a little bit more time demoing and get things in here for. I've been having a lot of fun using it, but please go and play. It's great to have your application live deployed to Flex and then go and click in an error report, go click on a stack trace and when you've got it set up, it'll go directly to your source code and set that breakpoint for you. Super duper cool. And I wanted to know, cause I didn't have enough time to talk about this. Tomorrow one of our coworkers is talking about debugging kind of a number of these Stackdriver products. So check that out. I've got a slide at the end here where I mentioned it. Finally, I'm gonna wrap up, but there's a trace tool that you get for free with gem Stackdriver to do latency tracing. I shouldn't be glossing over this cause it's really cool, but you'll get a great little chart. If you highlight any of your requests that maybe had a high latency, you'll get your Rails instrumentation, timeline of latency over there. It's everything you would normally expect. If you click into any of those, you'll be able to see like for each one of these calls and how latent they were, what the actual SQL is. This is really, really useful for debugging the performance of your applications. So, refresher there. Gem Stackdriver, go play with it. Check out cloud.google.com slash ruby. We've got good docs and launching off points for a number of the things we looked at. Check out the open source library. On GitHub, definitely check out this website. As I mentioned for our client libraries, this is one of my favorite sources of docs cause I use those, I happen to use those libraries a lot. If you can't tell, I love them. So these docs are awesome. And of course, go check out these client libraries pages. They're my favorite recommendation for when someone says, hey, how do I get up and running quick? Cause it shows you everything you need. I some shout outs to some of my fellow Googlers. Today at 2.40, there's a talk about natural language processing from one of our coworkers who is awesome. And that's talking about language and natural, natural language processing in general, not necessarily a gem. And then also tomorrow, what is my app really doing in production? Check that out. I'm really personally excited to see both of these. All right, so, got a little bit of time. Thank you. That's all I had. Good question. Really good question. And definitely come by our booth and ask about that, which I say because I know one of my coworkers would love to answer that. Oh, sorry. The question is, do we offer things for Chef and other existing orchestration tools in the environment? So it's a question like, do we offer recipes and things like that? We really rely on the open source community to have created those already. We do have an internal team that is an active contributor to some of those teams and projects like Fog. But currently, we don't push anything to Chef or anything like that. If you have ideas and would love anything, definitely let us know. Good question. The question is, how tightly is Stackdriver tied to Google products? And I wanna go so far as to say not at all. When you go to the Stackdriver docs, on the docs, you'll find at the top level ways to integrate it with AWS or call from any other cloud. I would love to have put in the configuration options here for us. So of course for Google Cloud, we make it implicit and simple, but everything we did here, you can totally do on any other cloud. Somebody maybe will tell me that's not the case, but I'm pretty sure every single thing because we call out to those APIs, they're saying yes. The question is, how does the pricing work? So it's based on compute hours or minutes or compute time. Someone would be better at answering this than I am, but it's the same that we use for Compute Engine. The thing that I get the most questions about or I like to point out is we have a sustained usage discount. One of the things that I believe is different with us is as opposed to having to do a bulk buy and have to figure out how many compute hours am I going to need in 2018, which some providers may do. For us, you can start using all those resources and get a sustained discount, but I think pull up the billing pages for Flex. I don't have the exact details for you. I can definitely answer your questions a little bit later. Yeah, it's based on our compute model. Good question. Yeah, the question is, I love all the stuff that you've made, but how come it took so long to incorporate Ruby into App Engine? So I can't speak for priorities for kind of the standard App Engine team, but I will say that one of the really exciting things for this kind of new App Engine flexible environment is that it's based on Docker. So that really opened the door for us. That let our team focus on making a perfect Ruby Docker image. That also opened up the door for, you can deploy dot net applications now actually to Docker containers on Flex. And a number of other languages that really opened up the door for us to be able to do that. So it was really the Docker that let us do it. And that's super cool. I hadn't used Docker a lot before I joined Google Cloud. And now, of course, I love it because not only can you use it there in App Engine Flex, you can take it wherever you want. There's no lock-in or anything to this. Any other questions? And of course, I'll be here after. And shout out, please check out our booth. We'll all be around and available to answer questions. Look for the Google Cloud shirts with the rubies and Google Cloud Ruby on the back. Thanks so much, you guys.