{"pageProps":{"source":{"compiledSource":"var c=Object.defineProperty,h=Object.defineProperties;var u=Object.getOwnPropertyDescriptors;var p=Object.getOwnPropertySymbols;var o=Object.prototype.hasOwnProperty,r=Object.prototype.propertyIsEnumerable;var i=(a,s,n)=>s in a?c(a,s,{enumerable:!0,configurable:!0,writable:!0,value:n}):a[s]=n,e=(a,s)=>{for(var n in s||(s={}))o.call(s,n)&&i(a,n,s[n]);if(p)for(var n of p(s))r.call(s,n)&&i(a,n,s[n]);return a},l=(a,s)=>h(a,u(s));var m=(a,s)=>{var n={};for(var t in a)o.call(a,t)&&s.indexOf(t)<0&&(n[t]=a[t]);if(a!=null&&p)for(var t of p(a))s.indexOf(t)<0&&r.call(a,t)&&(n[t]=a[t]);return n};const makeShortcode=a=>function(n){return console.warn(\"Component \"+a+\" was not imported, exported, or provided by MDXProvider as global scope\"),mdx(\"div\",e({},n))},ExternalLink=makeShortcode(\"ExternalLink\"),layoutProps={},MDXLayout=\"wrapper\";function MDXContent(n){var t=n,{components:a}=t,s=m(t,[\"components\"]);return mdx(MDXLayout,l(e(e({},layoutProps),s),{components:a,mdxType:\"MDXLayout\"}),mdx(\"p\",null,mdx(\"img\",e({parentName:\"p\"},{src:\"/mock-ups/time-frame.png\",alt:\"Apilytics Dashboard\"}))),mdx(\"br\",null),mdx(\"p\",null,\"Often times developers are proud of their newly created, shiny and \",mdx(\"em\",{parentName:\"p\"},\"beautiful\"),` APIs.\nBut what if they don't have the resources to analyze the real-life usage of their software?\nHow will they ever be aware of bottlenecks and other problems in their API\nif they don's set up proper monitoring?`),mdx(\"p\",null,`The issue with monitoring is however, that it is often not trivial to set up,\nas it might require you to build completely new infrastructure or modify your existing one or even implement your monitoring from scratch.\nThe other important aspect is pricing. The big players on the monitoring field are not cheap.\nYou might be fine starting with some of the most common solutions out there, like `,mdx(ExternalLink,{href:\"https://www.datadoghq.com/\",mdxType:\"ExternalLink\"},\"DataDog\"),`\nor `,mdx(ExternalLink,{href:\"https://newrelic.com\",mdxType:\"ExternalLink\"},\"New Relic\"),\".\"),mdx(\"p\",null,`As your API usage grows however, you will notice that your monitoring costs will increase significantly with the traditional solutions.\nThis is where you might consider either changing your vendor or building your own solution. This blog post\nshows you how to add monitoring using Apilytics to an example application built with `,mdx(ExternalLink,{href:\"https://expressjs.com\",mdxType:\"ExternalLink\"},\"Express\"),\".\"),mdx(\"br\",null),mdx(\"h4\",e({},{id:\"solution\"}),mdx(\"a\",e({parentName:\"h4\"},{href:\"#solution\"}),\"Solution\"),\"\"),mdx(\"p\",null,\"To demonstrate our API analytics solution we create an example REST API application with Express.\"),mdx(\"br\",null),mdx(\"p\",null,\"Let's start off by creating an express application:\"),mdx(\"pre\",null,mdx(\"code\",e({parentName:\"pre\"},{className:\"hljs language-sh\"}),mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-built_in\"}),\"mkdir\"),` express-sample-application\n`,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-built_in\"}),\"cd\"),` express-sample-application\nnpm init -y\nnpm install express --save\n`)),mdx(\"br\",null),mdx(\"p\",null,\"Then define our routes:\"),mdx(\"pre\",null,mdx(\"code\",e({parentName:\"pre\"},{className:\"hljs language-javascript\"}),mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-comment\"}),\"// index.js\"),`\n\n`,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-keyword\"}),\"const\"),\" express = \",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-built_in\"}),\"require\"),\"(\",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-string\"}),\"'express'\"),`);\n`,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-keyword\"}),\"const\"),\" app = \",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-title hljs-function\"}),\"express\"),`();\n\napp.`,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-title hljs-function\"}),\"get\"),\"(\",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-string\"}),\"'/'\"),\", \",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-function\"}),\"(\",mdx(\"span\",e({parentName:\"span\"},{className:\"hljs-params\"}),\"_req, res\"),\") =>\"),` {\n `,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-built_in\"}),\"setTimeout\"),\"(\",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-function\"}),\"() =>\"),` {\n res.`,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-title hljs-function\"}),\"send\"),\"(\",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-string\"}),\"'Hello World!'\"),`);\n }, [`,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-number\"}),\"100\"),`]);\n});\n\napp.`,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-title hljs-function\"}),\"get\"),\"(\",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-string\"}),\"'/foo'\"),\", \",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-function\"}),\"(\",mdx(\"span\",e({parentName:\"span\"},{className:\"hljs-params\"}),\"_req, res\"),\") =>\"),` {\n `,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-built_in\"}),\"setTimeout\"),\"(\",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-function\"}),\"() =>\"),` {\n res.`,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-title hljs-function\"}),\"send\"),\"(\",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-string\"}),\"'Foo!'\"),`);\n }, [`,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-number\"}),\"200\"),`]);\n});\n\napp.`,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-title hljs-function\"}),\"get\"),\"(\",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-string\"}),\"'/bar'\"),\", \",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-function\"}),\"(\",mdx(\"span\",e({parentName:\"span\"},{className:\"hljs-params\"}),\"_req, res\"),\") =>\"),` {\n `,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-built_in\"}),\"setTimeout\"),\"(\",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-function\"}),\"() =>\"),` {\n res.`,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-title hljs-function\"}),\"send\"),\"(\",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-string\"}),\"'Bar!'\"),`);\n }, [`,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-number\"}),\"300\"),`]);\n});\n\napp.`,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-title hljs-function\"}),\"get\"),\"(\",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-string\"}),\"'/baz'\"),\", \",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-function\"}),\"(\",mdx(\"span\",e({parentName:\"span\"},{className:\"hljs-params\"}),\"_req, res\"),\") =>\"),` {\n `,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-built_in\"}),\"setTimeout\"),\"(\",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-function\"}),\"() =>\"),` {\n res.`,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-title hljs-function\"}),\"send\"),\"(\",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-string\"}),\"'Baz!'\"),`);\n }, [`,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-number\"}),\"400\"),`]);\n});\n\n`,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-keyword\"}),\"const\"),\" port = process.\",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-property\"}),\"env\"),\".\",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-property\"}),\"PORT\"),\" || \",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-number\"}),\"3000\"),`;\n\napp.`,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-title hljs-function\"}),\"listen\"),\"(port, \",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-function\"}),\"() =>\"),` {\n `,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-variable hljs-language\"}),\"console\"),\".\",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-title hljs-function\"}),\"log\"),\"(\",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-string\"}),\"`Example app listening at http://localhost:\",mdx(\"span\",e({parentName:\"span\"},{className:\"hljs-subst\"}),\"${port}\"),\"`\"),`);\n});\n`)),mdx(\"br\",null),mdx(\"p\",null,`As you can see, now we have four different endpoints that each take a different amount of time to respond.\nThat's all of the code we need for our app. The next step is to set up our analytics.`),mdx(\"br\",null),mdx(\"h4\",e({},{id:\"adding-analytics-in-5-minutes\"}),mdx(\"a\",e({parentName:\"h4\"},{href:\"#adding-analytics-in-5-minutes\"}),\"Adding Analytics in 5 Minutes\"),\"\"),mdx(\"p\",null,\"Let's start off by creating a free account at \",mdx(ExternalLink,{href:routes.register,children:FRONTEND_URL+routes.register,mdxType:\"ExternalLink\"}),\".\"),mdx(\"br\",null),mdx(\"p\",null,mdx(\"img\",e({parentName:\"p\"},{src:\"/blog-images/problem-with-api-monitoring/signup.png\",alt:\"Signup\"}))),mdx(\"br\",null),mdx(\"p\",null,\"After signup, we will create a new origin to track our API usage.\"),mdx(\"br\",null),mdx(\"p\",null,mdx(\"img\",e({parentName:\"p\"},{src:\"/blog-images/problem-with-api-monitoring/origins.png\",alt:\"Origins\"}))),mdx(\"br\",null),mdx(\"p\",null,'From the menu, we will click on the \"New Origin\" button to add our API.'),mdx(\"br\",null),mdx(\"p\",null,mdx(\"img\",e({parentName:\"p\"},{src:\"/blog-images/problem-with-api-monitoring/new-origin.png\",alt:\"New origin\"}))),mdx(\"br\",null),mdx(\"p\",null,\"Next, let's copy our API key and finish up the integration in our example application.\"),mdx(\"br\",null),mdx(\"p\",null,mdx(\"img\",e({parentName:\"p\"},{src:\"/blog-images/problem-with-api-monitoring/api-key.png\",alt:\"API key\"}))),mdx(\"br\",null),mdx(\"p\",null,\"Let's install our client middleware.\"),mdx(\"pre\",null,mdx(\"code\",e({parentName:\"pre\"},{className:\"hljs language-sh\"}),`npm install @apilytics/express\n`)),mdx(\"br\",null),mdx(\"p\",null,\"Now let's modify our example application a bit to use the Apilytics middleware:\"),mdx(\"pre\",null,mdx(\"code\",e({parentName:\"pre\"},{className:\"hljs language-javascript\"}),mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-comment\"}),\"// index.js\"),`\n\n`,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-keyword\"}),\"const\"),\" { apilyticsMiddleware } = \",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-built_in\"}),\"require\"),\"(\",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-string\"}),'\"@apilytics/express\"'),`);\n`,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-keyword\"}),\"const\"),\" express = \",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-built_in\"}),\"require\"),\"(\",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-string\"}),'\"express\"'),`);\n`,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-keyword\"}),\"const\"),\" app = \",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-title hljs-function\"}),\"express\"),`();\napp.`,mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-title hljs-function\"}),\"use\"),\"(\",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-title hljs-function\"}),\"apilyticsMiddleware\"),\"(\",mdx(\"span\",e({parentName:\"code\"},{className:\"hljs-string\"}),'\"\"'),`));\n...\n`)),mdx(\"br\",null),mdx(\"p\",null,`Thats it! Now we have properly set up analytics for our API.\nNow we just have to run our application and spam it with some requests to populate our analytics dashboard with some metrics.`),mdx(\"br\",null),mdx(\"p\",null,\"Let's run the app:\"),mdx(\"pre\",null,mdx(\"code\",e({parentName:\"pre\"},{className:\"hljs language-sh\"}),`node index.js\n`)),mdx(\"br\",null),mdx(\"p\",null,`The application should now be running on your localhost port 3000.\nLet's do a few requests to different endpoints of our API. You can use your browser or another REST API client,\nlike `,mdx(ExternalLink,{href:\"https://insomnia.rest\",mdxType:\"ExternalLink\"},\"Insomnia\"),\" to perform your HTTP requests.\"),mdx(\"br\",null),mdx(\"h4\",e({},{id:\"analyzing-results\"}),mdx(\"a\",e({parentName:\"h4\"},{href:\"#analyzing-results\"}),\"Analyzing Results\"),\"\"),mdx(\"p\",null,\"After spamming our endpoints with some requests, we can analyze the results in our Apilytics dashboard.\"),mdx(\"br\",null),mdx(\"p\",null,mdx(\"img\",e({parentName:\"p\"},{src:\"/blog-images/problem-with-api-monitoring/full-dashboard.png\",alt:\"Route metrics\"}))),mdx(\"br\",null),mdx(\"p\",null,`We can see history of our request metrics visualized, but for this case it won't do us much since we just got started.\nThe interesting metrics here are the response times that we can see in the bottom right corner.\nWe can also see that our API has logged in total of 6 requests that we can see metrics from.`),mdx(\"br\",null),mdx(\"p\",null,mdx(\"img\",e({parentName:\"p\"},{src:\"/blog-images/problem-with-api-monitoring/endpoint-response-times.png\",alt:\"Response times\"}))),mdx(\"p\",null,`The bar chart allows us to easily analyze our response times.\nAs we can see here, our `,mdx(\"inlineCode\",{parentName:\"p\"},\"/baz\"),` endpoint is the slowest one by a margin.\nIn a real-life scenario of our API running in production, this might be a problem and the dashboard would point that out for us.`),mdx(\"p\",null,`Now this is just one example of how you can use Apilytics to monitor your API.\nThe Apilytics dashboard also allows us to detect anomalies during a longer period of time as well as spot trends in the usage of our API,\nget a grasp of the amount of error responses and much more!`),mdx(\"p\",null,\"There you have it! Now we have a way of analyzing our APIs and we no longer have to be blind about how they perform in production \\u{1F4AA}\"))}MDXContent.isMDXComponent=!0;\n","scope":{}},"data":{"title":"The Problem With API Monitoring","description":"Often times developers are proud of their newly created, shiny and beautiful APIs.","slug":"problem-with-api-monitoring","author":"Markus Blomqvist","authorLink":"https://twitter.com/blomqma","excerpt":"Often times developers are proud of their newly created, shiny and beautiful APIs. But what if they don't have the time to analyze the real-life usage of their software?","date":"2022-01-16"},"blogsData":[{"title":"Announcing Apilytics API","description":"Apilytics API is now available and allows anyone to monitors their APIs with Apilytics.","slug":"announcing-apilytics-api","author":"Markus Blomqvist","authorLink":"https://twitter.com/blomqma","excerpt":"So far we have been working hard to roll out Apilytics for developers using the most common programming langauges and frameworks out there, like JavaScript/TypeScript, Python, Node.js, Next.js, Django, FastAPI etc.\n","date":"2022-01-22"},{"title":"The Problem With API Monitoring","description":"Often times developers are proud of their newly created, shiny and beautiful APIs.","slug":"problem-with-api-monitoring","author":"Markus Blomqvist","authorLink":"https://twitter.com/blomqma","excerpt":"Often times developers are proud of their newly created, shiny and beautiful APIs. But what if they don't have the time to analyze the real-life usage of their software?","date":"2022-01-16"}]},"__N_SSG":true}