here to talk about refactoring. What is refactoring? A lot of you probably already know, but just as a recap, it's kind of restructuring or reorganizing or re-architecting your code and your files and your data structures and your directory structures and so on. So this could be like breaking long functions into smaller functions, moving code between files or between modules, renaming functions, things in general, moving files and directories around. But the important thing is it doesn't change the external behavior. So when you finish your refactoring, it should still work in the same way. So external behavior, in this case, could be like a web application. It could be, if you're writing a library, it could be your public API. That should stay the same. It's important because it improves readability of your code. It reduces the complexity of your code. And it's more maintainable, which means when you need to add a new feature or something, then it takes less time than it would if you got this massive chunk of code that takes you a long time to get into what's going on there. And most importantly, it's going to be a happier team. And future use is going to be a lot happier as well. That's an important person. So in general, the process of refactoring, the most important thing is to have tests in place. Now, when I say this, a lot of people assume that means automated tests. It doesn't. Automated tests are better because they're easier to repeat. But in general, if you get a process of steps that you can go through and repeat, then that will work as well. And what you want to do is make small incremental changes to your code.  If the test passed, then keep going. If the test don't pass, you've done something wrong, and you want to go back and change it. So in Elixir, I would argue that refactoring is maybe easier than in a language like Ruby or JavaScript, but probably not as easy as a language like Haskell or Elm, where the compiler gives you a lot of warnings early. Because all the arguments are past the function, which means when you look at function, you've got everything you need to know what's going on there. It's compiled as well. So if you made a typo, then you'll find out compile time. And this is especially true if you're doing something like working on an embedded device and you need to pull out your SD card, plug it in, and it's like, that didn't work.  So you get this at compile time. There's no dependencies in the file path, either. As long as your code file, your module file, is in one of the directories that gets compiled, it can be anywhere. And the test run quickly as well, which if you're going through a test every time you make a code change, it's super important that it's fast. Otherwise, you'll get frustrated. And there's some changes in Elixir 1.3 as well that make this easier. I don't think that was the intent, but as a nice side effect, it does. So there are warnings and imperative assignment. So this means if you set up a variable and then change it inside an if, then it's scoped locally. So you'll get a warning saying you shouldn't do that. And that was a 1.3 change. There's MixedXref as well, which will find functions and modules that don't exist for you. And this runs automatically when your code's compiled. So for example, if you've got a reference to a function that no longer exists because you've moved it, then you'll get a warning there. The compilation time is slightly faster due to the dependency tracking. And there's also X unit diffing, which is a huge change. And it looks something like this. So you'll see this is the output of a test. And the diff between the two strings when using the assert macro, the word lazy here has been removed, nor brown has been added, which is indicated in green for the word brown. OK, Elixir. So let's talk about Elixir and some refactoring techniques you can use. This is my application. It's called Pokemon Go 2.0. And this is what it looks like before refactoring. And this is what it looks like after refactoring. So the point about not changing your external behavior, that's it right there. So, oh, speaker notes. So the application looks something like this. Nope, this. So I've got these two web browsers here. By the way, the projector in here runs 720p, not 1080, which means that the windows are tiny, but it will make do. So the way the game works is you go into the home page and you can view the challenges. And there's currently no challenges, so you can create a challenge. And then it goes into this waiting state where it's waiting for another player to join. And you can refresh that, and then you'll just wait in the waiting state. And then in the other window, you can come along and view the challenges. So hey, I'll join a game with example user. He sounds like a cool guy. So you join the game, and both of them have updated, even though it's here. And you'll see that the current turn is x. So x always goes first, but the person who's x and the person who's not. This is tic-tac-toe, by the way. We call it knots and crosses. I'll use the two terms interchangeably. But the player on the right here is the x's and the player on the right's the knots. So you can't play when it's not your turn, because that would be weird. You can play when it is your turn, but you can't override an existing piece when it's your turn. Play continues. It's like a battle to the death until one person is declared the victor. And they get a sweet message saying you won, and then the other person lost. So that's it. I had to disable my Wi-Fi as well, so unfortunately I can't let you play once I'm doing this. But that's it. So the winning criteria, if you've never played this game before, then that's weird. But it's one of the classic board games. But just in case, you need three matching pieces in a row. There's three horizontal wind lines, three vertical wind lines, two diagonals. And if all the spaces are filled and none of the above criteria are matched, then the game's a draw. So in code, it looks a bit like this. I apologize if the code's quite small again, projector. But the way the code works here is I've got a condom there and it says, so I'm destructuring the list, which is how the board's represented. There's nine elements in the list. I'll get onto why I'm using the list later. And then three conditions. So I've got the three horizontal lines represented first. So I'm saying if A is equal to B and B is equal to C and it's not nil because that's the default, then that means there's a piece there and someone's won, the piece A in this case. And then it's kind of okay for the horizontal wind line. You can kind of guess, okay, D is equal to E and E is equal to F and those letters come next to each other, so they're probably next to each other. And then you've got the three verticals. You've got A, D and G. And then you've got the diagonals and it gets quite confusing. And that's deliberate because it's a refactoring talk. So, and then I was saying like, if any of the pieces are nil at all, then the game's still in play and return false because that obviously means the game's still in play. And for any other clause, which is the true, it's a draw. So all the pieces have been filled and no one wins.  Get blame. And it turns out it's this guy. And I use a scientific technique here called defactoring which is when you take a piece of code and make it worse. The whole commit message here is actually defactor, make game server function awful. And that's why I did. So we can refact this, right? So we can use a technique that's called if to pattern matching. It's fairly descriptive about what it does. So pattern matching is one of the core concepts in Erlang and Elixir. So let's take a look at how we can do this. So instead of having all these ifs and saying it's A is equal to B and B is equal to C, we can have pattern matching. So we're pattern matching on the list and here we see the first three elements match and it's not nil, unfortunately, I have to put that in. Then the piece is one. Same for the second horizontal line and the third and then the three verticals and then two diagonals. And it's a little bit more readable and we still got the draw case at the end. It's more idiomatic now because we're using in so we're saying if nil is in the board then the game's still in progress otherwise it's a draw. I showed this to someone and they're like ah, it doesn't seem more readable and I went okay, fine. There's a side by side comparison. So you see there's no like, you don't have to know what A, B and C are or G. But you can also do this, which makes it a lot clearer.  You can define your function over multiple lines. And here like the mat, the layout of the pattern match here is the layout of the grid and you can clearly see that we're looking at these three pieces. So you'll see that technique as well and like maybe people making a poker game or something and you wanna check that the suits match. You'll see a similar technique. So that's if to pattern matching. It's one of the more common refactoring techniques. Use multiple function heads and in my last example the layouts match the data structure. Excuse me. So let's talk about the application. The way the application is structured is there's challenges that are stored in the database and that's when I clicked on view challenge, great challenge, they get stored in the database. There's a game server, which is a gen server that holds the state of the game, which is like the players who are in the game, the state of the board, whose turn it is, whether like the game's in progress or not. And then there's like a registry that maps the IDs of the challenges to the PIDs for the gen servers. We probably won't look into the code in that, but that's what it does. And then all the communications handled over Phoenix channels. So here is the gen server. So there's three functions here, start link, which is a wrapper around gen server start link. It's pretty common in gen servers. We have a join function, which joins the game. And then we have a play function, which plays the game. This is like the public API. And then we have the init function. So here you'll see that it returns okay. And then the entire state, which at the moment is a map. The board is a list of nine elements, which I use the list because later on I was gonna talk about how we could change that to a better data structure, like a tuple. I guess if there's like a tuple with three elements, I'd like to call it a triple. So I guess a nine element tuple would be a nipple. So the player's an empty list. The state is waiting, as I said, the X is all start first, so X terms true. There's no winner and there's no win line. So the function is deliberately like obfuscated. So the first clause is saying when there's less than two users in the room, then check that the user's already there. And if they are, that's fine, just return state. And that's why refresh works. If there's like a new player, then prepend them for the list. If they're the only player there, then they go into a waiting state. If both players go in, we shuffle the list of two elements and that's how we randomize who places which marker. And the game goes into a started state. And then we update the state and return that state. And then we got the second clause here for the join as well, which says if the user's in the game, that's fine and they can play. Otherwise, the game's full and they've got no business being there. Like if you've ever tried to play this game with three people, you got like the knots, the crosses, and the triangles, it doesn't work. So the other thing we got was play. So again, we check if it's a valid move and that means it's within the bounds of the grid. Like you can't place a piece, a negative index. You can't play a piece that's further on. And you also can't override an existing piece. I'll show that function in a minute. And then we say if it's the user's turn, so the way we do that is if they're the first player and it's the exit turn, then we return okay, zero. I'm using zero and one here to represent the knots and the crosses because it's a talk about refactoring. What you should actually do in this case, maybe use an atom for like a knot on a cross that'll be way easier to read. So it's just a little thing I put in there. Otherwise it's not your turn and you can't play. Then we take the result of that and we pipe it through a case and then we work at which piece it is. We update the board using list.replaceaxe, using a list. And then we update the state, we check if the game's won using game one function I showed earlier. And then we update the state. If there is no winner yet, then we just invert the X turn and it's the other person's turn. If it's a draw, then the game's finished and there's no winner and if it's ending else. X is a terrible variable to use here because that's got context to this application, but that's whoever wants. That should be the winner. And they get assigned as the winner and then the line gets set so it can be highlighted in the front end. And then ending else will return an error. And here's the valid move function. So if the index is less than zero, then it's an invalid move. And if, so we're using enum.act here, which means that it has to be within the bounds of the list. And instead of returning nil, which is the default value, because that's the default value of the board, we're returning invalid, which means that nil is true and ending else is false, which is, again, deliberately confusing. And here's the game one function that we got earlier. So why refactor this, right? It totally works, but it's difficult to read. Like I wrote the code and I was struggling there. There's some unnecessary duplication. I don't want you to think like, all duplication's bad, that's not true. There was a case of left pad in NPM where some duplication would have been good. So a little duplication's bad and a little dependency. But it takes some time to understand and get in the zone of what this code's doing. So next thing we can do is a technical case to function. And what we do here is we're looking out for nested cases. And this is something that a lot of beginners to the language do. They'll put like just cases, because it's easy. And that's fine, but there are different ways you can approach this. So it helps prevent this cases and removes like horizontal code in favor of vertical code with like named functions. And the functions have names, so it's more descriptive of the intent. So this piece of code here for the join has a nested case. If you can't see it, it's this case here, which is inside an if. So what we can do is just move this to a function called check all players present. And now we don't have a nested case. We have a function call instead. The function looks exactly the same as the case did before. It returns a tuple with the players that are in the game and the state of the game now. So that was it, that was all there was to it. So the next thing we can do is move the callback code to functions. So this is a similar technique. When I'm writing a gen server, I like to keep my callbacks pretty small and pass off to some helper function. And the same goes for like a Phoenix controller. You don't want like lots of logic in your controller actions. You want to move out to helper function. So it's more descriptive because they're named again. It's very similar to last factor, but the test should still pass because, so the test was gen server, I forgot to mention, are a little bit complicated because the public API is so small and you don't know who's playing first. So you need to work out who's turn it is by trying to join and it'll tell you who's turn it is. And then you need to, based on who's turn it is, send different play commands and work out all the states for all the wind lines and all the draw conditions, which is a little confusing, but it works, so the tests are there so I'll probably keep them. So let's look at the join function again. So we've got this clause here and instead of having the entire body like we've got here, we can call a join user function. So this is still the clause when there's less than two users and the join user's like the helper function. So it updates the state. So we're passing the whole state object and I'll get onto why we're doing that shortly. But it's quite a common technique for state transformations to pass the entire state through. So here's the join user function. So again, if the user's there, that's fine, return the state. Otherwise update the game players. So I've renamed this function, which used to be called check all players present to update game players. And that's because now it returns an entirely new state. And if we look back up here, you'll see that the state is replied to here. You'll see that's what gets responded to the web socket. There's still these two clauses though. We can consolidate these down into one clause that looks something like this. So because if you're there, then it returns okay in the state. And because if you get added, it returns okay in the state. So we can match on the join user function and check for the state. And if it's okay state, then we'll update the state and return the new state. Otherwise we'll keep the existing state and reply with whatever was returned, which is probably gonna be an error. And the join user function now is makes heavy use of pattern matching. So the first clause says if there's one user in the game and it's me, then that's cool and return the state. The second clause says if there's two players in the game and I'm either player one or player two, then that's fine return the state. You'll probably notice here that instead of saying when user ID in players, I've got to say when user ID in P1, P2, this is because guards need to be available at compile time. So I need to build it manually. And that's why I use that. In the next one, we call our update game players function as we did before. And for anything else, the game's full. You can not play. So if you look at the diff so far for the join function, we've got the, this is what it looked like before, where it was just everything was in the handle calls. This is what it looks like now. So it's not actually shorter, but refactoring is not about writing shorter codes, about writing more declarative code and more understandable code. So up next is the play function. So this will use similar techniques to the join function. So I'm not gonna go through each function in detail, but we're refactoring into functions and then we'll go on to something different. So here's what it looked like before.  But it now looks like this. So we've got one function. It looks exactly the same as the join. We've got some case and then we do something, whether if it's okay, otherwise we return the error. And then we've got this update game state function, which updates the game state. Go to the valve move function, which I had before. Then we've got the player's turn, which checks whether, you know, your player one is the X turns and so on. The play turn function takes a state and it places the marker and then updates the game win state based on if someone's one or not or if it's a draw. The place marker updates the board and the game win state just checks if there's a winner and returns them. So let's talk about case to pipeline. So this was pretty common pre-Elexer 1.2 and what you would do is you wanted your function to read the series of transformations. If you can't spot it, look out for the pipeline operator. So we've got this function here, which looks a bit ugly because we're, for some reason, piping into a case and we could just call case in the function, but let's ignore that for now. And instead of writing it like this, we can write this, so we can say state and then check if the move is valid, check if it's the player's turn and then play the turn. The problem with this is that we need to know what's happening with the response so we can no longer just return what we want. We have to wrap it in some way. So we start by returning okay from the valid move instead of making a boolean and then in each function here we have to match and say if it's an error, return the error and if it's okay, something, then that's fine and we'll use the state. Same here, if it's an error, return the error. So we have to constantly tag our values whether it's an error or not an error. And what we can do instead of this, so this was pre-1.2 and it was a big problem and there was lots of posts on the mailing list about it and everyone was writing their own monad libraries, there's about 14 monad libraries on hex. Don't use any of them. You can actually, I'm not here to tell you what to do. So the case to pipeline though, so there's a built-in solution. So the problem with case to pipelines, it makes the first function look nice but you have to modify all your functions and their return values. Instead, we can use something that was introduced in elixir 1.2. It's probably my favorite thing that's been introduced to language. It's called width, I use it all the time. It removes the need to change your function heads but it still reads the series of transformations which you'll see in a minute. It enforces matching at each step which will make more sense in a second but you can also assign inside the width. So here's our pipeline and here it is using width. So when I say it has to match, it means that if the valid move doesn't return okay, then the width will stop and it'll return whatever the result of valid move was. Same with okay marker, player's turn doesn't return okay marker, then it'll return whatever the result was. And then here we're using an assignment here so we're saying the new state is this and then do sort of return the new state. And then in the case, if we get okay state, then that's fine and we'll return that. If we get anything else, we'll return whatever was returned. So when I say it still reads as a pipeline, as a series of transformations, it does, you just have to shift your eyes about 20 characters to the right and then that works. But there's still a problem here which was fixed in elixir 1.3 which is this part here. So piping into case is, it's a little bit ugly but it's quite a common pattern when using width. But what we can do instead is elixir 1.3 introduce with else. So we can now say with something do and that's the positive path else and then we match, it matches the same like a case would match. So we say for anything else return that result and that's the whole function there. So that's kind of all the functions looking nice now but they're still using a map for the state and what we can do instead is just struct which is a construct that's built on top of maps so it's a map with an underscore, underscore struct, underscore, underscore key in it that points to module. You can match on structs as well so you can say only this struct is valid for this function. Ensures the correct types as well and that's especially true for using something like dialyzer then you can specify types to your modules. So you get the compile time guarantees and you can implement protocols on top of them which I don't go into in this talk but the gist is that maybe we'd wanna implement the inspect protocol for our game and then when you output to the terminal it shows us like an ASCII version of the grid should've done that thing. So here's what a struct looks like. You call def struct inside your module and the contents here have just copied from the map so it looks exactly the same except it's now structured and we now can return the default game state in our init function instead of having the whole map in there and then each function matches for that particular struct which is a game struct. If you try and call this function with anything else then you'll get a match error and I've just updated that all the way through the file. So now we have this module that we can use for our struct so we can move all the functions that we've defined now over to that module and that means our code and data together which is really useful because you can see what you can change. It's easier to test as well because you've got all these functions now so before we had to set up the gen serve in a particular state which you can also do with sys.getState and updateState or writeState but I had to play the game for the test to work whereas now I can test my edge cases in this particular module and you can module.false or .false particular functions you don't want people to depend on and you can still test them and that's quite a good technique. So here I've just moved all the functions over so this is now the game module and all the functions exist in there and then here instead of just calling the local join user function I'm calling game.joinUser or game.updateGameState. Okay so that's elixir. The techniques are fairly applicable to any library you're using so that's why it took so long. We'll talk about Ecto now. So a common thing in Ecto is counting so this is what it would look like prior to Ecto 2 a lot of people writing code like this and what we're doing here is counting the challenges for a particular user so we get the user we get their associated challenges and then we use a fragment to get the count and then use repo one to ensure one results returned and I used to see a lot of people so I picked my things that are discussed based on like what comes up all the time on mailing lists or Stack Overflow and what you can do in Ecto 2 is use repo to aggregate which is really nice it takes a queryable and it takes some form of aggregation which is like a count or an average or a sum and it takes a field so you can repo to aggregate. So one of the things that we do in this game is we fetch the open challenges for a user and then we increment a field on the users called refuse challenge count under the assumption that like they're so good that no one wants to take them on anymore because if you've ever played this game you'll know that after like four games all games end in a draw and then we'll remove the challenges from the database because we don't need them anymore we need to stop all the processes for the games that are run because we start the process when you join the game as the first player so we can stop those now and remove the pins from the registry so we can use a new feature in Ecto 2 called Ecto Multi for this so it's kind of like a pipeline but for your database transactions but you can also run arbitrary functions in here which I've got an example of so currently we use a transaction so we have this repo transaction on line seven and we're using with now because I've shown it so I can use it so we say update the user and then if the user updates successfully then delete all the challenges and if the challenges are deleted successfully then stop the games and the reason we're doing this order is because if we like delete the challenges but the games don't stop then we no longer have a reference of which challenges existed so we'll never be able to stop the games for that and anything else we use repo.rollback which rolls back the entire transaction so here's the functions this one negates the age to get all the old challenges because it's not like a daytime subtract function Ecto is only daytime add if you add a negative value that's the same subtraction so we get all the challenges that are older in a certain time period and fetch them the delete challenges composes a query for all the challenge IDs that we have and calls delete all on them the stop game maps over the game registry calling delete game on each element and then the update is using a change set and updates the refuse challenges with the count that we pass through so what we can do instead is use an Ecto multi so you start with Ecto multi new and that starts multi-struct and then each time you add a function you give it a name and when Ecto multi returns it returns a map of the name and the particular value that was returned when you execute that function so instead of updating the user directly we pass a change set and then that will be called to the Ecto multi update same deletes instead of deleting the users directly we call delete challenge query which returns a query which then gets passed the delete all here's a function so the argument that gets passed that we're ignoring is the state of the multi this far when it's executing and we're calling stop games but we're ignoring the argument and then you can pass that to it you pipe it through to repo.transaction so these functions now return queries instead of actually executing and the other thing is for a multi to succeed and each return okay something so that's why we're returning okay something and not just okay so Ecto multi returns a data structure that you can pass into transaction but that's not the only thing you can do with it it's quite easy to test as well because you can pipe into two lists and then perform assertions on it so that's useful for like testing it in isolation they get executed in order from top to bottom so if anything fails then it'll stop executing the entire multi pipeline and it won't run if you got change set errors as well so it doesn't even need to go to the database to fail it can fail if you got a change set validation error so that was Ecto multi let's talk about Phoenix so what was that so the Phoenix generators are as we always say a learning tool so they're fast to get up and running and by default this is what will happen so if your get from the repo returns like can't be found then it'll show 404 which by default looks like the bottom right picture there and if you got 500 errors they say you're using UUIDs and you pass a non-UUID then you'll get an internal server error so what we want to do instead you can customize these pages by the way but that's what they look like by default so what we want to do instead is if you can't find or there's a 500 then we want to show flash message and redirect the user to like the list of challenges probably show you what that looks like looks like this yeah looks like that so that's an error but when it doesn't raise an error it'll be fine oh actually I'm using a different branch that way so what we want to do is override the action so this is something you can do in Phoenix controllers the action is called at the end of the pipeline and by default it calls apply with the action name for the controller and it passes in the con and con.params so here is the generated controller I've omitted the index creating new actions because they're not relevant for this particular example but you'll see that this line here appears over and over again in each function and that's the thing that will raise that will trigger the 400 or the 500 error what we can do instead is we can override action it's def overwriteable in Phoenix controller so here I'm assigning the action name to act name because both action and action name are taken by Phoenix controllers you have to come up with something new I'm using with again and I'm saying if the action is either show edit update or delete then find the resource and if it successfully finds the resource then we call apply on the module with the action name but we pass this additional third argument which is the challenge else so this is matching on the else of a width if it's false then we apply with just the two arguments so this will be true for index creating new and if we get error not found then we'll put a flash message saying not found redirect back to the challenge path and then halt so find the resource function looks like this so we're saying if the UID is castable then it's about UID and we'll continue and then if we can find the challenge then we'll return okay challenge and otherwise we'll turn error not found and that's the thing that matches that triggers the flash message and then in all the actions here so instead of calling like the repo.get inside the controller we can have this third argument here challenge and that's passed through to each of them so yeah so overriding action allows for explicit parameters in your actions they can come from anywhere as well so you can also define a custom controller so maybe you've got like a user that you want to use in several controllers you can define your own controller and then use that instead of using my app.web controller and that'll work as well so the other thing we can do instead is like find with a plug so plugs are pretty common in Phoenix like the whole thing is a series of plugs a plug is called before the action we can combine it with the previous technique as well so you can use a combination of the plug and defining an override you can use function plugs or module plugs if you use a module plug then you can use it in multiple places but if you use a function plug then it's got to be local to the controller and I've scrolled there so we call it with plug so we say plug find resource when the action is one of these actions and then our find resource function now looks slightly different we're still doing the with but if it succeeds then we'll assign the challenge on the conduct signs otherwise we'll put the flash message there and then we'll return we'll redirect the challenge pass and they'll see the flash message I know what we can do instead is use conduct signs.challenge so here I actually didn't need to keep this in but I have for demonstration purposes so because it's already on a signs we can just go ahead and call render directly but I'm passing it through explicitly here to show you the difference between the previous version and you'll see that it's in all of these conduct signs.challenge instead and if you were to combine the two techniques you could just check conduct params in your action override and then pass it through as a function argument so there are a couple other things in Phoenix that I should probably mention the first is that plugs can be used in most places you can use them in the endpoint so I've used this before to check if you're on a subdomain or not because you can only have one root to a particular resource in your router in the router as well a common place a common reason you do this is if you want to guard a particular set of roots behind authentication or authorization then you can use a plug in there and then you can use them in controllers as I saw so the other thing that I should mention is you want to try and keep your modules web-focused this is kind of what Chris was talking about yesterday where you want to pass off to some other module in some sort of context or domain that does all your logic that's not web stuff the general technique I use for this is to keep report your controllers so you can just open up your web.ex file delete the alias for repo and then watch everything break and then slowly fix it and this also has the benefit that it allows other interfaces into your domain so the web isn't the only way into your application you could also maybe have a mixed task or some other way to your domain logic so in summary you want to keep your team in future you happy write more maintainable code and reduce the technical debt and yeah, that's it, thank you this is me I'm Gazzler except for Twitter where I was late and I'm the Gazzler I work at a company called VoiceLair to push the talk stuff and the repo is open source and each change is like a commit so you can go through and step through these examples thank you by the way I had a question about so the multi with the non-database interaction point so with the multi if any of the individual commands that are happening there there are database related that would be like within a transaction presumably is that accurate? the whole thing is a transaction so you're piping the whole chain of things you built up into a transaction so if you wanted to have that non-database related thing not apply maybe just always put it as the last piece of the multi you can put it any way you want as long as it returns error something then the multi will stop if it returns okay something then it will continue through the multi but I want my non-database related thing that I put into a multi to also roll back well that depends on what that thing is if you're stopping things in a gen server then after you've killed the paid you can't resuscitate the paid it's gone it's dead so in that case you just have to think about how your application works in that particular case putting the end is one way having some sort of fall back in place or if you can't kill it is another maybe you could persist the state first then if none of them if they don't all die then roll back and keep the state as it was perhaps yeah you're right you need to think about that okay thank you let's wait until we there are examples there where you're talking about going from horizontal to vertical and I've had that same idea but when I put stuff in a function heads the guards end up out in column 60 or 70 so there's got some tension there so I haven't really figured out how to do that right so you got horizontal but not nested so you can write your guards across multiple lines as I did in the first example with the grid and that's fine so maybe you can have the arguments to your function on separate lines and guard against each one individually but you're right that totally happens all the time and you need to find a way to fix it any time I'm unsure about code style I just go to the elixir repository and look at how they do it and spend hours searching for an example and then just copy that does that answer your question? anyone else? I think that's it okay thank you very much


Ephesians chapter 2 made alive in Christ. As for you, you were dead in your transgressions and sins, in which you used to live when you followed the ways of this world and of the ruler of the kingdom of the air, the spirit who is now at work in those who are disobedient. All of us also lived among them at one time, gratifying the cravings of our flesh and following its desires and thoughts. Like the rest, we were by nature deserving of wrath. But because of his great love for us, God who was rich in mercy made us alive with Christ even when we were dead in transgressions. It is by grace you have been saved and God raised us up with Christ and seated us with him in the heavenly realms in Christ Jesus. In order that in the coming ages he might show the incomparable riches of his grace expressed in his kindness to us in Christ Jesus. For it is by grace you have been saved through faith and this is not from yourselves, it is a gift of God. Not by works so that now you can boast for we are God's handiwork created in Christ Jesus to do the good works which God prepared in advance for us to do. Therefore remember that formerly you who were Gentiles by birth and called uncircumcised by those who call themselves the circumcision remember that at that time you were separate from Christ excluded from citizenship in Israel and foreigners to the covenants of the promise without hope and without God in the world. But now in Christ Jesus you who once were far away have been brought near by the blood of Christ. For he himself is our peace who made the two groups one and has destroyed the barrier, the dividing wall of hostility by setting aside in his flesh the law with its commands and regulations. His purpose was to create in himself one new humanity out of the two thus making peace and in one body to reconcile both of them to God through the cross by which he put to death their hostility. He came and preached peace to you who were far away and peace to those who were near. For through him we both have access to the Father by one spirit. Consequently you are no longer foreigners and strangers but fellow citizens with God's people and also members of his household built on the foundation of the apostles and prophets with Christ Jesus himself as the chief cornerstone. In him the whole building is joined together and rises to become a holy temple in the Lord and in him you too are being built together to become a dwelling in which God lives by his spirit.


Mm-hmm.  Who's the little girl? She's got a zit in her ear That'll hurt. You know what else hurts When somehow some way you Try to yank your catheter out. Hey, welcome back to our shape of the raxi at the Corby Scram Twitter for more juicy content Don't do that kids yank your catheters out. No, just do it. Don't yank your catheter out Cowboy and Catherine Happy birthday America Two shootings in one day What a what a way to celebrate? today We got a trailer. We saw the teaser for this. We need a third part like a good third party We need like a 10 because like we've got the red and the blue which is part of the American flag So they should be there, but we're missing the the one that's the white color that could really like that's the Republicans They were they were the Republicans of the red. No, they were the white the Democrat We got a Molly Alderman trailer called auntie Sundarang Nikki and it's with Yeah, something like that. It's with Nani and Nazria Nazim remember that name. Yeah, I do. Who is it? It's your mother's sister's aunt's cousin's nephew's brother's uncle She's a count actress, but she's also Exactly what I said Anyways, but we've seen the teaser for this a little while ago, right? I think it's like a family with the thing that that ended with Fafa and she was walking alongside of them What yep Here we go What I Don't have rain They've seen the first photo And to keep up with it. I can't do anything.  I'll be keep you safe I'll give it to you Me to the land we I'll do it. I'm going to do it. I'm going to do it. I'm going to do it. I'm going to do it. I'm going to do it I'm going to do it. I'm going to do it. I'm going to do it I We're out of the way. What should we do now? There's one more option left. What's that? Dude, what did you say that was good? What did you say that was good? Isn't it good? What? So, tell me. I'm telling you what I was saying. I was telling you what I was saying, and you didn't tell me! That's the New York Library. I guess I'm guessing she is she's Muslim and and he's Hindu and I mean we know he's he and his family are Hindu and I'm guessing she's Muslim or Christian I don't know and that that anything yeah there's a there's a lot of stuff that I think was over my head that I I don't really know exactly what's going on from the trailer yeah I think it's mostly just these two want to be together I think clearly and there's obstacles right are on opposite side and going to America has something to do with it yeah maybe you'll open to America yeah but she got caught I don't know I can't tell I don't know what to expect and maybe that's a good thing I think it's like it's more just I think almost like an Eushman style of family comedy yeah where you're gonna kind of deal with some family generational and discriminatory trauma yeah I guess you could say yeah save me oh okay so a Hindu Brahmin okay that adds that takes it up a notch falls for a Christian girl and trains her to be a Brahmin to convince his parents only for their plan to be revealed okay I didn't fully grasp it's almost like but I do yeah a little bit but that's obviously not a so you're not a revolutionary concept to it's been in film for a long time you need this person right they're not who your family wants so you convince them to be uh I mean they've been a man woman gay whatever it is would you pick a category that your family won't approve isn't white chicks like the essentially they become white chicks yeah I haven't seen that I know people love that in the old film soul man the what I don't know that that even wants to be seen anymore today but it started um see Thomas Howell it's called soul man it was about a white guy who wakes up black wow yep did he do blackface yep but in like a fun way that Robert Downey Jr. did black yeah in that way but his wasn't like Downey's like full immersion method kind of a thing his was legit he just wakes up one morning and he's a black man and they used the same actor it wasn't like he just that would have been funnier you know like in big the kid wakes up and it's Tom Hanks so it's a completely different person portraying the character but no Tom Hanks I mean big it's rough it's kind of creepy it's it's a little creepy the girl starts falling for him yeah as she knows he's a child yeah she knows that he's a child in a man's body and yet he's still like she's still like I want you sir it's good it is a little weird it is a little weird as most old films are but it hangs on to the premise of the reason she's appeal there's an appeal there isn't because he's 13 it's because too many guys aren't more child like gross yeah not child ish child like so yeah I yeah that I I have no I can't tell and that's not the trailer's fault but also mine I can't tell from the trailer we really like the teaser but that was a little shorter and sweeter I do remember we liked it but also how many Malayalam comedies have we seen like in terms of just because I always run into that that fear if it's a comedy that that kind of always on obviously this one's gonna rely heavily on Hindu stuff and obviously always Christian stuff obviously we both Christian in so it's like like that stuff but that last I guarantee that last one was really funny because it was something was on TV something was on TV it sounded like it was a cooking show where they were cutting up meat and they walked in like why are you watching this and he switched it over to a channel with mantras and they're like I think that's what was going on but clearly that's the thing about comedy so much comedy is often cultural specific situational situational like words wording yeah subtitles don't always no they exactly what it the the comedy yep that's always the fear yeah sometimes it works completely I mean but I do was absolutely fantastic yeah they're much harder to do because you have to get universal agreement on the comedy of what you're doing and and so often comedy is very to the point now culture where you are I mean if you see roasts of people it's almost always going on with like the culture of the now so and that's why oftentimes we were better now than we were we pick up on stuff a lot better but we have a long way to go before we're able to pick up what you guys can pick up oh yeah as obviously if you're not in America you can't pick up on all references if it's an American comedy right it's obviously it's different because that you you also speak English fluently in most of you yeah very true they're way ahead of the game that helps yeah and you are all for the most part you genuine stupid babies are a lot more attentive and pay attention to international affairs and often know more about America than a lot of Americans yeah I'd say so aside from the English language yeah but very much aware of both are not only what's going on but the negatives prime members save 60% switching to an annual IMDb per member wow interesting anyway let us know what you thought about the trailer what should be our next Malayalam oh what happened Fafa's film got a release date oh good when I think it's the end of August great I think cool we finally got some confirmation good film is still alive yeah anyways I just wanted to point it out let us know what you thought about the trailer which be a next Malayalam film we should watch down below


Welcome everyone to the first webinar in our LFX series introducing the LFX toolkit today we're going to be diving into the LFX insights tool. So you'll learn today how you can learn a bridge data to make more informed decisions about your projects performance beyond the code. And just to get us started a few of housekeeping. Sure, we're all familiar with these zoom calls and how to leverage chat and webinars, but we will be monitoring the chat, as well as the q amp a very regularly throughout this. We'll try to address some questions, you know, live, excuse me, some questions live in the chat, but we'll also have plenty of time at the end to really dive into any, any more questions that that will come up throughout. So please ask away in chat, as well as in the q amp a feature and we will be on those sites. I want to introduce the team that's here with you today for our webinar. So she brought car will be the presenter. So he's going to walk us through the LFX insights tool, giving us some context around LFX overall, and then diving into a demo of the capabilities. He is our CTO and GM of products and so he's very very closely aligned with these the tools that we built out here. Myself, as well as our technical product manager such in Gupta will be moderating so we will be on the chat addressing any questions, we will be fielding the questions for the q amp a at the end. And if anything else comes up, we will be there to support as well. So with that, I'm going to go ahead and hand things over to shoe breath so that he can dive into what we're all here for today and talk through our LFX toolkit and specifically LFX insights. Thank you. Thank you for attending everyone. So, you know we have been working on this product, particularly the Linux Foundation engineering team for almost a couple of years now. And, you know, as we are bringing this LFX chain of tools, the primary purpose why we build these tools are to, you know, build more sustainable open source projects during the entire lifecycle. So, how can we actually help these projects succeed right. You know, again it's will be pitching to the choir if we say the world runs on open source, but the critical projects, they need more than, you know, a source control system or version control systems or a one off tool here or there. You know you need help growing these projects and become those category leaders. So projects. The first thing, you know, is that you know you need to have a finger on the pulse of the entire ecosystem, not just the code, right. And there are tools that you know there should be tailored to the key stakeholders right the stakeholders could be maintainers contributors community managers outreach committee members the governing board market years and much more. So, over the last decade or so the Linux Foundation and in all its sister foundations as an entity have evolved a proven methodology to help address these challenges and you know transform you know early stage projects pledging projects into those category leaders right. So, the LFX tool chain that we're going to talk about it essentially operate operationalizes this approach, or this methodology, and we have a set of tools to you know help. Those are built to facilitate every aspect of the open source development lifecycle. So there are 12 tools in the tool chain, and as we go through this year next year will be adding more and more of these tool chains into the kit. Today we're going to focus primarily on insights but just to give you a super high level in, you know, headline here. Security is the one that we have built to look at vulnerabilities in the projects, you know software bill of materials license compliance and whatnot. We have an individual dashboard which essentially serving creating a community profile. Also, primarily meant for users to, you know, get their badges, whether those are training certification badges, manage their code contributions, and so on. Obviously, many projects have been using tools like ECC LA for managing, you know, contributor license agreements, or whenever they are contributing code as an individual as a corporate. We last year we had in the same toolkit we had launched mentorship. Most Linux Foundation projects are already leveraging this platform to grow the community. We have a crowdfunding tool as well, which projects are leveraging to raise money and funds and spend it where they feel fit whether it be on infrastructure development documentation travel events or not.  We have a community events tool that we built, essentially if you're running your own project branded meetups. How do you actually raise money for those meetups how do you effectively, you know, run different chapters. We have a training portal where you know you have 40 plus training courses and certifications available to grow the skill set. And finally, these two project control center is something we are launching late this quarter. This will be focusing on automation of all it resources, legal resources, your project challenges that you face when you know you know bootstrapping a project or day to day maintenance or you want to grow those right. Remember supporting member companies, we're also building an organization dashboard so that you can actually see your impact on all open source projects at least those projects that are within the, you know, our home and find their home in the Linux Foundation. So today we are primarily going to focus in on insights. The platform has been created by the internal engineering team. And we obviously had a lot of partnerships like we leveraged others open source projects has is the norm. And so in insights, you know, fundamentally, right, why did we build it. So unless we start measuring how we are doing on those projects, there isn't much room for improvement. And often in open source projects is you know, the visibility is limited to an individual developer or a contributor or to a maintainer. How can we get an entire ecosystem view right. So, if I look into, you know, you'll see some stats on the right, and those stats are growing. So these are the numbers we we are already instrumented 375 projects and you know every other day we are instrumenting more and more projects that find home at the LF. But so far we have been looking at like code velocity right there could be lines of code like we already have like 1.15 billion lines of code, but how much is changing on a weekly basis right like how much gets added how much gets deleted. So we are looking at like how much is changing developers like is that contribution count growing right like our communities growing. Where do they work at like who are our supporting companies right so we really found out we were close to like, you know, 12,000 plus companies and these developers this contributors spread are spread across these companies. It really gives you an idea of how they're distributed and how diverse our community is. We have implemented, you know, 11,900 repositories and that count is going up. We're looking at like, you know, annually 8.9 million commits, you know, more than a million pull requests more than a million builds, you know, issues that are logged in Jira GitHub issues like in a bugzilla container downloads right like from your registries how on the downstream adoption how many people are pulling down those images. Right we have a variety of collaboration tools whether it's on chat on email. What are the formal groups right where are they communicating what is the activity there. So great metrics there's much more to look here but fundamentally what our projects have been we found out our projects are not, you know, bound to a particular stack as is the norm in open source we are distributed by nature and in our choice of tooling. We could be running our projects on GitHub, get lab, get, get it. We could be using everything from a slack to a rocket chat to hip chat to you name it like to a discourse to communicate you could be maintaining documentation at 15 different places and that's preserving that choice is important. Because, you know, not one slight size fits all for all projects, but how do we really get the insights with this distributed nature right so unless we get those insights. There are some problems everybody's trying to solve as the project right like yeah our projects code velocity slow. We have a big community of contributors, but where are those bottlenecks right our development pipeline is clogged we really don't have an idea of where exactly is it clogged is it in you know the. The workload on the maintainers is it clogged somewhere else we are able you know unable to identify who our top contributors are right and not just contributors in terms of code, but also influencers in our communities right it could be particular individuals it could be particular companies, and you know many times you know we put out great code but our user adoption kind of is not matching. You know our code velocity, but we don't really know it's just a lack of awareness, it's the code quality, what really are these issues right so this is our effort to give you those kind of insights, that's why we built this product. Okay, so different personas right one tool and we have tried to build different views for different personas primarily for the maintainers and the project leads we are getting trying to give you a 360 degree view. Right, there are fundamental problems you want to solve you want to avoid maintainer burnout, you know those are the key people in your community who are merging your PR is reviewing your code. Contributions come in left and right but you know the last thing you want to do is you know burn out your maintainers and longer term how do you ensure your project health security and sustainability right like security for many projects mean sustainability. For the outreach people in those projects you're evangelists right how do you attract more members more funding and grow your community and awareness right. Again, unless you understand, unless you're able to measure how your campaigns are performing, you won't be able to you know improve there. For our all our supporting members corporate sponsors for them, you know, a lot of these contributors are working with a full time employment at your companies.  Right. How do you not just evaluate or like you know, encourage like your employees making contributions to certain projects but also how do you encourage that behavior. And again, also in terms of when you are investing into particular projects how do you find out you know which other member companies are sponsoring those projects are participating to what level. And fundamentally for all developers open source developers in our community, like the goal is like where to focus your efforts on right. You know showcase your leadership, you know you have a lot of active contributors maintainers there are leaderboards there are some people who put in heroic efforts. But like you know we need to grow equitably so and the other part is like you know once you make a contribution. How do you manage that affiliation right is that contribution on your own behalf is it on behalf of your company how do you measure that impact. So these are the primary personas who can start using the tool today. List features you know this list is going to be endless but just as a snapshot, you know we have a multi dimensional 360 degree view it's multi dimensional reporting that you get out of the tool. We have utilities for contributors to manage their affiliations and their identity. We have created these leaderboards or contributor boards so every project can slice dice the data maybe use those for elections as an example. There's shared innovation whatever instrumentation we build whatever dashboards we build for a single project, every project gets it right regardless of like how big or small they are. We have a trajectory from multiple data sources and then we're also as we are increasing the ecosystem visibility we are looking into different areas right, not just code velocity what is your marketing impact just as an example. Today we support, you know, 15, around 15 data sources and it's growing and then by the next quarter will probably be around you know, 18 or 19 data sources. So the ones, you know, these are like fairly evident like from source control systems like you know anything get based get it based GitHub from issue tracking if you're using bugzilla GitHub issues or jeera for tracking all your issues. You know if your collaboration is primarily happening on groups.io. That's where majority of our community mailing lists are our mailman for a lot of other projects. If you're looking at continuous integration CI like we today have instrumented Jenkins from a registry perspective you're you know distribution channel. We've got Docker hub for our media, particularly if you're doing press releases contents indication SEO we have instrumented session documentation, Confluence, you know chat rooms we started with Slack, found out communities like Twitter use rocket chat we added those and there are more coming so I think the next set of wave you will see will be an increased focus on social media. So Twitter, LinkedIn, Facebook, we are increasing our focus on different type of build systems, you know, GitHub actions is coming up a lot, Travis CI circle CI get lab. We're mailing list so they're so distributed now we're going into Google groups right so this will keep growing but just wanted to give you a snapshot of what is supported today and what's coming relatively soon. Okay. Just talking about affiliations right this is probably the most important part of like how do we, you know a test credits for your contribution. So there are multiple ways this attestation is done. All these project data sources that you see here that's where we are getting our data from. However, these data sources could be GitHub, it could be get it could be a mailing list it could be a Slack server it could be a conference document it could be your social media board. Everybody uses a number of different IDs there's no seeing you know unique way to stitch these together into like saying that okay this was the same person. So what we've done here is, we are already like instrumenting and getting this data into our leaderboards. However, we have three ways to, you know, update the affiliation, the number way and way for particularly for projects who are primarily you are driven like there's a good DM methodology it was not a new concept was started by the Linux kernel years back and you know was used by CNCF as an example as well for their affiliations.  Sometimes you want to that code contribution to be attributed to your employer, which is essentially a corporate contribution. So you can essentially issue a PR and that good DM repository is what we essentially integrate with our leaderboards. The second way to do it is which we were doing from a long time was have community admins essentially every project has a set of community leaders. And they essentially know who the community who the top contributors in those projects are and they can manage the affiliations on behalf of the community. But to make it really scale we went with a self serve approach. So we have built a UI and that UI is available in your community profile where you can as an individual contributor that contributor could be in any area doesn't just have to be a code contribution we discover your contributions and then you can you know self attest there you know how do you want your contribution to show up in these community leaderboards right and many people change jobs right. So how can you keep that continuity and while you are earning badges those badges could be you know speaking at events that could badges could be with your training certification that could be with your skill set, or you being a mentor those badges are also displayed in those same profiles. Okay. So quickly jump into a demo. Let me share my screen here. So how do you get to insights. First of all, so there are multiple ways. I think the easiest way is to do insights dot LFX dot dev. That gets into the homepage. Here, you will see there are n number of projects like we have a structure of cards. So projects which are, you know, clustered together in project groups, you will see, you know, they are grouped together like Academy Software Foundation, it's initially a project group. However, there could be a standalone project called as Bitcoin core. There could be a group of projects for if you look at CNC F, you know, cloud native computing foundation that probably has 70 projects underneath it. So that's how we just the modality that we have.  Let's take the use case here of hyper ledger. If I jump to the entire hyper ledger project group, you, you know, we have high level statistics that we have built to track like the performance of that entire group of projects holistically. And then you also have like, you know, that data project by project by project. So right here, out of the gate we are seeing, you know, 15 odd projects that are under hyper ledger and then they have a lab environment as well. And many projects they create like a commons, right, like which are like shared utilities so you can instrument those and look particularly as those but these are kind of aggregated numbers. So let's look at these snapshots in time. So, you know, if you're looking at a particular project, let's say, you know, if I want to go and look at a particular project areas as an example, you get that specific filtered view for the project. However, if you really want to look at from a group summary we aggregate the data across that entire project group. Okay, so let's look at some interesting statistics so we talked about source code contributions right. You know, if you start looking at commits, right, that's that's where we start. And the way we have been working these is like we, you know, start tracking those commits, regardless of the source they're coming in from and these are all time filtered the default range is always 90 days you can go back and you know look into last year last two years last five years. You know, pick relative scales and then we slice dice the data based on again this is based on your affiliation data, like you know those commits, which organizations are they coming from how many lines of code actually changed. You know, who are the active contributors, like, like in terms of diversity, how are those commits spread out by time zones again UTC timing. If you want to filter for a particular organization, you can. So, you know, you can just simply apply a filter like that. And in this case, you will see just a view for IBM, if you're just filtering for IBM, right, as an example. You start looking into you know, information around the authors, like who are the top authors in that time period like in again based on commits lines of code added removed average files. You're also filtering that by organizational impact. You're looking at repo by repo which are your most active repositories which are your most active projects. Again, this gives you a good handle on the velocity and then also like you know we get down into you know commit hash and like the commit URL so you can get as deep as possible, or you can you know look at it from our top down approach as well. However, you know, commits are great but what about the efficiency right so yeah there are pull requests coming in and you can have similar views on PRs. And as these contributions are coming in and similarly you can slice dice the data in terms of you know PR submitters repositories over time how these are doing. Again, how many are open how many are closed. You know who are the top, you know submitters of this PRs and so on, but we are starting to now go into like how are these peers doing from an efficiency perspective. We leveraged a lot of the best practices that were set by chaos as there's a big initiative there or a project they're called metrics and a lot of specifications and best practices were provided there on key metrics to measure right so if you're thinking about like, okay, PRs are great but I want to start looking at like what's the average lead time right to merge that PR. You know what's your kind of moving average there is it increasing is it decreasing. Is it happening more iteratively. If you start want to start looking at you know what your timing on disease right like average time these day open. You know you can start looking at those distribution charts like how exactly is the performance happening right. It's healthy 95 percentile of open time is decreasing that's actually a healthy pattern you should not want it to go up and up and up. Interesting metrics to look at. Similarly, you know if you wanted to just get into data like builds right so I'm going to go and use quite a few different projects because you can navigate and cross compare across projects as well. Okay, great code came in PRs are happening approvals are happening in if you're in the get it land you want to also look at like reviews and approvers so I'm not going to go into all those metrics but they are there. If you're looking at builds you want to really understand like okay what's my job performance right how many jobs am I running on a monthly basis quarterly basis, how many jobs succeeded how many failed how many unstable how many got aborted. Are there like large spikes like this happening into the system. This does not point to an anomaly. It could be normal.  But again this is interesting to data to look at and analyze right we start looking at like okay what are your primary, you know, jobs like and you know are they how are they trending upwards downwards the bill duration of those jobs. If these jobs are running for days maybe that's a good area for you to start optimizing these right. Similarly, you know there are many more metrics here if you're really looking at you know your registries and let me go on to another project here. And if I want to track like okay how is my distribution doing, and I want to start tracking it from you know Docker her perspective, right like what are my top images again this is within this time period. How is like you know the pools happening and you can probably like if you start trending this over like a you know six months and year is this increasing decreasing right like what are the top images that are getting cooled down so it also points at an adoption this is not a user pulling down it could be a CI job pulling down your images, but you not starts looking at like okay how are we actually performing outbound right in terms of the adoption. Now, again, many more metrics for the technical consumers for the consumers who are looking at the ecosystem. You know you might want to start looking at things like, you know, your slack conversation so if I go into let's switch projects again. On the CNCF site and I want to look at the entire project group and look into like okay. Let's look at slack right a lot of projects on CNCF you shared slack resources. You know, again you can put a lot of messages like who are the top people who are the top participants in those official channels we are not looking at peer to peer conversations we are primarily focusing a lot on like you know the official channels which the projects want us to instrument and start taking a look at you know what are the topics in those channels like what is the purpose of those channels. Where are people what are people really discussing right what are they trying to solve. There are many areas where like if I switch back to a checks foundry. I might be able to even look at the same data but in this case for slack. You know there's a section here many projects have you know provided us some keywords to look at right. So you definitely want to eliminate all the filler words, but you want to look at like what's trending what's not trending are there certain keywords you really want to track. You can actually start measuring you know what's important what are people talking about in those communities right. But as I said, not everybody uses slack we had a similar implementation for a project like hyper ledger where instead of slack. They use rocket chat right so we tried to build similar kind of you know data interpretations, regardless of the chat system you are using. You know what the participants what are your top reactions what are the keywords should be looking at and whatnot. So this is again if you're looking at collaboration right many projects are using for email conversations groups.io. And then again you can see like who your key participants are which are your busiest mailing lists, where are these people participating from where are those recent messages so we are streaming in all these messages as well. And these are your most active mailing list right this is an indication of how you know your, you know your participation across the community is trending it's going up going down. So what are those like if you have an underperforming mailing list why exactly right, are they not important topics that are getting discussed how do you increase that. Okay. I'm not going to every section like documentation I think what one good thing worth looking at is, you know, earn media. So social media, yes, it's still we are going to publish it in the next few weeks, but right now we have got on media. Let me look at CNCF one more time. And look at like the own media so what do you start looking at under on media. So things like mentions. Okay. So if you look across the board, where are your mentions happening. You know, and which are your social amplifications channel. You know what are your hotspots right this is kind of a United States view. But again, these are like where your content is getting mentioned. Right, it's not just like where your users are, but where is your content trending.  So look into like, you know, across the world where your, you know, content readers are right like primarily yeah the US dominates most of it but here you can also see like China is becoming a very big hotspot for CNCF in this example. Okay, you're looking at things like share of voice. So, again, a lot of these are like keywords based on what the projects want to track their share of voice but if you had like one. This is lamb down Kubernetes will always be the 800 pound gorilla in the CNCF group of projects. But again, if you look at project by project right which which is you're getting the most share of voice here you are just comparing against other projects in your group, but you can also compare against proprietary tools other open source that are out there right so and we are able to stitch this data. We have led done a lot of partnership with the content aggregators to pull this in amount of information. How is your sentiment doing right how much is positive neutral negative. If you're putting in some key messages how are they performing overall right and this could be like keywords based key messages based right.  So different ways to slice and dice the data to start looking at your impact also looking at like how to improve that some good things to look at. I'm going to again switch back to another project here. Here's an example of on app. You want to start using some of this data for voting. Right. And again, this is more around contribution data. So how do you do your TSE elections as an example right so you could just be looking at code, and you can see here, you know people with their names and you know organizations that are working on their email is not visible. I see it because I'm a super admin in your case as you will be seeing it without the emails, but you could be looking at okay code is one criteria. What about tickets, right or people who create issues. What about documentation contributions right is that like, do you want to capture and see a holistic view, you know, across the board, what are the different parameters based on what you're going to do a voting like who consider top contributor. Is it just the person writing code, or doing commits, or is it a person who is making an impact across multiple areas right so we can add more data sources you can export this data use it for a lot of, you know, election voting process as well. Another interesting thing to look at is. You can compare projects side by side. So if I start looking at Okay, let me look at like past three months and let's compare some like projects so if I'm gonna. Again maybe Kubernetes is probably not a great choice because it's a big super big project, but let's compare it against something like gRPC. Let's compare it against Prometheus. We are kind of in the same family of cloud native projects. Again, you know, when you are looking at, you know, see three months, six months. Is it the number of commits looks like it's trending down but is it necessary a flag, you should not draw interpretations from just the number of commits going up or down. You know, different set of metrics to gauge the health right so we are just providing you the raw metrics, but the analytics of whether a trend going upward or downward is pointing to health. A lot of analysis needs to go in there right so just if something is trending downward doesn't necessarily mean it's bad it could be actually be good. So we have been working with these projects to get a set of like what are the key metrics that are valuable to look at, but you can even go and you know, go across projects of a similar group so I can say okay. Let's look at Kubernetes versus fabric project in Hyperledger. Let's see how that does right completely different project different ecosystem. How do we doing on the same set of metrics now these are like very, very detailed we are trying to build some high level views as well though so we can easily compares again different timeframes per se. So, a lot of things I would really encourage you to check out all these features in there, and you know, check your projects in cases where you find like hey we don't have data. It could be that we don't have this data source for information to instrument. In some cases, we might not support the data source that you know your project is using.  Okay, so I'm going to go back to my deck here. Okay. And also want to talk about roadmap so what's coming next. So I'm not going to be able to demo all of this, but the next big feature release that we are going to do in a few weeks is social media analytics. Very deep dive social media analytics around you know your Twitter followers your LinkedIn posts how they are performing how you know who the who your followers are your Facebook fans type of content that's working not working images versus video versus text copy. Where are those people distributed are you gaining supporters are you losing supporters and whatnot right so this is coming very shortly. Later half of the, you know, q2 q3 onwards. We are obviously adding more data sources that's going to happen on a regular cadence. You know, all the CI systems is our next big effort, and also getting into Google groups Microsoft teams again we are taking these requests from the projects where they feel the critical mass it what are the key data sources they want to look at. We are also adding event participation project by project training and certification participation project by project events could be both virtual and physical. So that's why like when I talk about metrics it's not just code that's code alone doesn't make your project. It is the most important component, but there are many other areas in the ecosystem. There's another view we are trying to stitch together which is essentially looking at the entire pipeline. So think about like the core to ship pipeline or even you know all the way from where you actually log an issue to the way you know some contributor picks it picks up the issue works on it issues a pull request reviewer reviews the code merges it. I mean, and that particularly essentially as a maintainer it gets packaged into some build job, the build job runs it's put, you know, into some package management system, the distribution happens so can you look at it end to end right. And I think you will start to see this kind of an in I would say it's completely inverted funnel where you know a lot of inbound will come in in terms of issues feature requests but over as you go through this funnel. You know, the people who are towards the later half of the funnel are essentially your gatekeepers they are the most important people in your community, but we'll start to stitch this impact view end to end so you can start measuring different types of metrics on a plane. Okay. So opening up for questions. And before we go into more questions I just also wanted to give you some highlights into some resources. If you really want to update your affiliations you can go to this my profile screen. I'll show you how to do that there are like you know these are the links to the app, how to get connected stay connected with the newsletter, you want to get support add data sources your project is missing something. That's the place to go, you have general questions come to us, but I just wanted to show you one area where affiliations are done which is the self serve UI. So just here, this is my profile anybody who has a Linux foundation ID actually already has this. So if you log in, I am a developer I can see my code contributions across all these projects. And if I wanted to say like hey I'm contributing on behalf of the Linux foundation, or I'm contributing as self and maybe my data isn't correct right this was like source from LinkedIn or whatever data we had on, you know, two third party systems. I have an ability to say hey you know what, I don't really work here anymore. This should be based on. Okay, I am just as an example, I change jobs at this point I was working at Google, and I was a maintainer or a contributor, and for this project during this time frame. My contributions should be affiliated to Google, or it could be just affiliated to myself. So this is a self serve utility that every developer every contributor, again, contributions could be across the board they get to see and you can use this to update your profiles and once you update these in the leaderboards that you see in your insights dashboards, they get automatically updated so that's why you know for us communities to scale we are providing the self service utility. So let me stop there and open it up for questions. Awesome. Great. Thank you so so much she brought everyone if there's any questions please add them to chat or go in the Q amp a. I'm going to bring back that final slide so that we all can see that as reference with all of our links. Just give me one second here but please go ahead and start dropping in some questions. One that I know comes up a lot she brought that love to address is, you know how do we how does a project get access is there a cost for Linux projects, and how can a project get these dashboards, you know up and running for their for their project. Yeah, so for this tool is provided for all Linux Foundation projects there is no getting per se. The easiest way to get your project on boarded is to just create a support ticket in our Gira system the link of that is in our technical product manager such in heroes on the call will pick it up and help you with the onboarding the way the projects get on boarded is we give you a set of Google sheets where you need to provide us the data sources that you want. This project uses like what those endpoints are that we should be instrumenting. Many times we ask you for like okay what are the keywords that you want to look at right so provided that data we can on we have a lot of automation all these dashboards get generated in automatically, you will be able to onboard a project in a couple of days right it doesn't take more than that. From an cost perspective like there is no hard cost here like this is being managed through your membership support or the support of the membership that is done through the projects but it's one service that's provided kind of to all projects right like. Yeah, an individual doesn't have to pay for that. What we do have is there are some features like the ecosystem metrics because the members are primarily funding them. Those are gated for you know employees or all our contributors who are working with these supporting companies or if these contributors or people are part of formal governance committees of these projects like the TOC the marketing committees the legal committees the board. But for the technical metrics like anybody in the world can come and see that, but this whole thing is funded essentially out of the membership support that we get from these projects. So it's like, but again, that's primarily like infrastructure costs that are shared by these projects, but other than that there is no expense for say. Great. Thank you. One other question that I saw come up through the Q&A was around, you know, the understanding which data sources are connected for their project how does a project understand what the data source, which data sources are already connected for their project and be able to get, you know, other things added as needed. Yeah, great question. So if you don't mind sharing I can actually show you it's you can see it in the tool itself. Yeah, so if I share my screen, and there are a couple of ways to look at it. So the number one thing is just look at your project. And if you're looking at your project group. The quickest way to look at it is, you know, data source is not configured you can see here for pages like our documentation. There's no data source configured or there's no data here. But also if you look at your summary, and you're going through these main dashboards, you can see here with support, get it get up now your code could be not be on get it then you don't care. However, there could be a project let's assume you know you are in CI CD. And you see here Jenkins, we support Jenkins, but it's not configured for this project. Okay. Why, because my team doesn't have the endpoint for Jenkins to instrument. So if you just create a Jira ticket here and give us the endpoint, we can put in the enable this instrumentation or registry information right if you if your registry right now isn't Docker hub and you know you have a Docker hub endpoint or the actual Docker hub account we should be looking at. We don't have that information if you provide it to us like we can enable this like super quick. Does that.  Yes, if it is not supported let's say issue management G it hub issues bug zeal. So this project uses get up these are the only ones we support tomorrow let's say we add a third or fourth system which is get lab issues. Right. So it's not supported yet but like if we don't if you don't have then let's say you know, you are using bug zeal and we are not seeing any for bugzilla that means we don't have your bugzilla information what is the URL what is the host, what is the port, and what is the key to look at right so that information if the project sleep can provide us in a Jira ticket, we can set it up right away. Awesome, great. So we might have time for just one more question here, if there are any in particular that have come up as we've talked through the demo that maybe we haven't addressed in Q&A. Oh, here's a great one. How let me go ahead and bring this up from our Q&A that we addressed earlier on how does a project or how does anyone identify the state of a project maturity is that something that can be understood in the inside dashboards or is that something that's coming on the roadmap. Yeah, from what we're it's a roadmap item for us but what we are trying to do is like look at certain best practices and like start creating some maturity indexes. This is a little bit. I would say subjective because like how do you define maturity now there are projects which have been there for 15, 20 years, and there are adopting some of these best practices, like the best practice could be like you know your PR efficiency could be a best practice. You know your contributions like, let's say you know more iterative contributions versus you know, one big bank contribution of a million lines of code. And there are projects, you know you can't enforce it as a hard rule, because there might be some projects the communities work that way, right but in general iterative contributions are a best practice, right. So what we're planning to do is we'll come with a set of specifications and will be creating indexes maturity indexes on different areas, right. Here we can actually post that maturity index but you have to take it with a pinch of salt, because you know it's just a recommendation. It's not an absolute hard rule because project communities can differ in their best practices from here or there so it's really based on best practices. So yeah, like, you know, from a maturity perspective. We don't have a set of indexes defined today. That's a short term project for us. Thank you. So, I think this is, we're at time at this point. If there are any other questions that come up. Please, you know, feel free to reach out and we just bring that slide back up to for everyone to see here. You know, feel free please is next steps, go in and update your affiliations, explore the insights dashboards for your specific projects and, and others. Please do follow us, stay connected on our newsletter, because we will be sending out, you know, all of the new data sources that she was talking about and other features will be sending out updates for that through through the newsletter. And of course, if you have any questions or need support on getting started, you know, reach out to us through our support channels as well as asking questions. And we will be sending in follow up, we will be sending out an email with our recorded webinar, as well as if there are any questions that you know come up in at the end here that we might not have addressed. If there's any feedback from from all of you who have attended our first webinar, we would love to hear that too. So thank you all again for joining us and have a wonderful rest of your day.


What is up trade hackers? Happy Friday, November Third 2023 only two trades today. It's a Friday. So sometimes things aren't Somewhat muted on Fridays not much volume Start off with a Boba mighty 90 turned into a winner Plus 210 that Tesla mighty 90 plus 230 total 440 and the week So let's take a look Boba Had a mighty 90 right here and then it pushed up and so I got filled up here about highs of day It came down and I got out of I got filled with $1.30 And I I was thought I was I thought I put in a dollar 45 to get out a half But I got I had I had put in a dollar 35 instead of a dollar 45 some mistake on my part so And I'm getting out of half and then When it pushed back up it got back up to here I added to it at $1.17 and then when it came down I got out of $1.30 and then and then after the second red bar cut the rest of $1.33 so a Nice little trade got two consecutive red bars added to it Plus 210 would have been probably more if I would have waited Or not if I would waited if I would have correctly entered my 10% fill the first time instead of putting in a dollar 35 if I would have put in $1.45 probably would have gotten filled when it pushed all the way down to here on that And then Tesla So I had this volume pop and it pushed up one more time to highs of day So I got in right here And I was gonna add to it, but I didn't get filled It came so I think start coming back down so I canceled my my ad and then it came back down I got out of all but a couple of contracts and then on this one I ended up finishing up and getting out of the rest so That's really it. There was some other mighty 90 potentials, but I wasn't doing more than two at one time. So I'll take this right here, you know for a Friday never know what you get on Fridays with price movement and volume So I'll be back next week. Hope everyone has a great weekend. Peace


He just turned 17 years old. And when you look at him, you think you see a man. He's a kid. So far, Cordy is struggling to solve the puzzle of David Togan. It's a lot of war, and he hasn't seen his parents in four years. Now you're getting a kid who's trying to figure it out in America. I told Ewan, who are you going to feed? Are you going to feed the negative dog, or are you going to feed the positive dog? He kept feeding the negative dog inside of him. What's going on? Fuckin' boy, I don't know how to pass Big Man Wolf. All right. Fuckin' self-to-shit. This is not a deal.


This is Ace, the most photographed person that G.I. Joe Collins has done. Okay, so I did change one year. It's not like that. It's like us. You always in costume together. When we're harmed at this parachute drop. 22 years of doing this. So again, it's my fault. I'll let you know that tomorrow is a very important day. It is Becky's 30th anniversary. So don't make it mine too. So happy anniversary here. And before I talk here, we're going to have a few people come up and give very short comments. So somebody wants to hit the top, hit number one. In no particular order. Let's have the most photographed individual of G.I. Joe Collins that's ever been. Mr. Ace Allgood, would you like to come up? The only reason why I had so many photos in this is because I took so many and kept sending them in. It's very self-serving. The only thing I want to say, I want to be very brief. I've had out of the 25 years, I've made all but two. And I've had a great time in each and every one. But what makes each and every convention unique and special is the time that we get in face time together. This is not the internet. This is not eBay. This is where we can all talk and make friends. And I want to say to each and every one of you, three and three quarter ones, for our guys. Thanks for keeping us 12 inch guys around. And we are all in this together. Now the other thing I want to say briefly is, this is not the end of the world. This is the beginning of the next chapter in our lives. That's right. There are other conventions. There are other shows. There's always that evil internet out there. So thank you very much for everybody. And thank you for making my life complete by giving me this great toy show, Brad. And the adventure continues. So, Ace was talking about that he missed a couple of shows along the way. Probably one of the people I want to recognize, I'll talk about my staff when we're in it boys a little bit later. But Heather, stand up, Heather, is the only one that's been to every show that we've done. Besides me. So that's one record. But, you know, at the end of the day, there's only two people left standing. Charles, where are you? Come on up. So Charles and I are the only two people that have been to every licensed G.I. show show there's been. We've been to all of them. So Charles, I'm going to turn it over to you. Hey, thank you very much. But I remember the very first show that I went to that Brian did. I thought it was interest about like five, three and three quarter dealers in the room and everybody else was 12 inch.  And then you see how it is today. But one of the things that Brian has done, you know, people realize for 22 years, Brian has kind of kept the convention package pretty much about the same price. And it's always given us a great value for what we've got. I don't know too many companies or folks that could do that. But even when Hasbro wasn't producing product, Brian's still pumping stuff out for us guys. So I think next year you're going to notice it's going to be a little bit different. But, you know, I just kind of keep that in mind. I'm glad that we had these adventures together. I say everybody keep in touch. I know there will be something new just like he said. There will be a new chapter. But, you know, this is kind of the one opportunity to kind of do the big group hug and talk about Joe's, have fun for a few days together. And let's keep doing that, guys. First thing that we were going to call up, that he's already talked a whole lot last night, was Darrell the priest. And so really Darrell said, I don't think I have anything else to say, but we want to thank Darrell again for the induction last night. And I think that says it all right there for Darrell. So thank you again, Darrell, for everything you've done. So Todd, Pleasant, come on down. You're the next contestant. Okay, I'm going to say everything that everybody's already said. So we'll scratch that. I've said this over and over again. It's the people. It's not the plastic, it's the people. You take the plastic home, you display it, sometimes you dust it, whatever. But what you're taking home is memories that you're going to have forever and people that are going to be your friends forever. My first night at my first show, I was doing room-to-room trading and I ran into this dude who's doing room-to-room trading and we see we compared lists, we weren't looking for the same things, so we became friends. We went room to room to room. At the end of the night, we introduced each other. His name was Darrell the priest. Okay. The next day I went to lunch, Darrell introduced me to two of my best friends who I record a podcast with every week and I talk to every day. Available on iTunes. Available on iTunes. And Stitcher. But this is the thing, that was 1999. Okay. And we saw, like I said, we thought we saw was the end of our era. But it kept going and then we met new people, great new people. And it's just, this never ends, people. As long as there's all of us, as long as we care about this stuff, it never ends. It goes on forever. Plastic, not people. All right, I'm trying to alternate between different scale of collectors, not them, but the action figures they collect. James Kavanaugh. You'd like to come on, man.   That was mean, Todd. That one croaked. One more time for Todd. It also simply said, Jokon isn't a place.  You can't. It moves. It's all in us. I'll tell you the first time I ever met Brian, the year after I did.