{"id":36485485,"url":"https://github.com/esumit/metric-apis","last_synced_at":"2026-01-12T01:49:00.545Z","repository":{"id":83697072,"uuid":"385452795","full_name":"esumit/metric-apis","owner":"esumit","description":"MetricAPIs is a conceptual logging and reporting service designed to aggregate metrics within specific time windows, focusing on the most recent collection period. This service streamlines the process of tracking and analyzing key performance indicators in real-time.","archived":false,"fork":false,"pushed_at":"2025-07-15T09:25:29.000Z","size":336,"stargazers_count":0,"open_issues_count":17,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-15T21:10:08.307Z","etag":null,"topics":["golang","microservice"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/esumit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-07-13T02:48:46.000Z","updated_at":"2023-04-10T02:08:10.000Z","dependencies_parsed_at":null,"dependency_job_id":"182a52a3-b969-4fd5-af7d-080288464df3","html_url":"https://github.com/esumit/metric-apis","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/esumit/metric-apis","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esumit%2Fmetric-apis","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esumit%2Fmetric-apis/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esumit%2Fmetric-apis/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esumit%2Fmetric-apis/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/esumit","download_url":"https://codeload.github.com/esumit/metric-apis/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esumit%2Fmetric-apis/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28331253,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T00:36:25.062Z","status":"ssl_error","status_checked_at":"2026-01-12T00:36:15.229Z","response_time":60,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["golang","microservice"],"created_at":"2026-01-12T01:48:59.925Z","updated_at":"2026-01-12T01:49:00.536Z","avatar_url":"https://github.com/esumit.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"#### Metric APIs\nMetricAPIs is a conceptual logging and reporting service that aggregates metrics by time window based on the most recent collection period. \nThis service offers two key metric endpoints: posting metric data for a specified metric key and retrieving the sum of metric values for a specified metric key.\n\n#### Demo Recording\n\nhttps://tinyurl.com/metric-apis \n\n#### How conceptually it works ?\n\n![Screenshot Request: metric list for posting and retrieving metric data - active_visitors ](/images/metric-apis-flow.png)\n\nThis  metric apis service have implementation of two metric endpoints:\n\n###### 1. post metric data for a metric key e.g. active_visitors\nWhen a POST request is made, the service stores an integer metric value for a specified metric key (e.g., active_visitors) \nas a data model (CreatedAt, Key, Value), assigns it an ID, and saves it to a metric list data structure. \nDuring every insertion, the service checks if each element's CreatedAt time falls within the current time \nand the most recent COLLECTION_TIMEOUT window. If not, the element is removed from the list. \n\non success, it returns the id of created metric-data in the list. \n\n````\nPOST localhost:9000/metrics/active_visitors\nResponse:\n{\n    \"value\": 20\n}\n````\nThe service uses a sync.mutex to lock and unlock during each insertion.\n\n![Screenshot Request: post metric data for key - active_visitors ](/images/Metric-POST-ByKey-2021-07-15.png)\n\n\n###### 2. Retrieving metric data for a metric key e.g. active_visitors\n\nWhen a GET request is made, the service calculates the sum of metric values for a specified metric key (e.g., active_visitors) \nwithin the configured time window. \n\nIt traverses the list's elements, checking if each element's CreatedAt time falls within the most recent COLLECTION_TIMEOUT window. \nIf it does, the service calculates the sum of the metric data values, count of metrics, collection start time, and collection end time, and returns the data as JSON. \nThe service uses a sync.mutex to lock and unlock during each retrieval.\n\n````\nRequest : get metric data for key - active_visitors\nGET localhost:9000/metrics/active-visitors/sum\nResponse :\n{\n    \"start_time\": \"2021-07-14 23:44:10\",\n    \"end_time\": \"2021-07-14 23:47:30\",\n    \"metric_count\": 6,\n    \"metric_key\": \"active_visitors\",\n    \"metric_sum\": 64\n}\n\nRefer start_time and end_time :\n- Its configured based COLLECTION_TIMEOUT env variable \n- On this example its 200 seconds \n\n````\nWith its ability to log and report metric data efficiently, MetricAPIs provides a streamlined approach for tracking and analyzing key performance indicators in real-time.\n![Screenshot Request: get metric data for key - active_visitors ](/images/Metric-GET-ByKey-2021-07-15.png)\n\n\n###### Code Structure\n\n````\n➜  metric-apis git:(main) tree\n.\n├── Dockerfile\n├── Makefile\n├── README.md\n├── dist\n├── docker-compose.yml\n├── go.mod\n├── go.sum\n├── images\n│   ├── Metric-GET-ByKey-2021-07-15.png\n│   └── Metric-POST-ByKey-2021-07-15.png\n├── main.go\n├── metric_benchmark.sh\n├── metric_get.sh\n├── metric_post.sh\n├── pkg\n│   ├── config\n│   │   └── type.go\n│   ├── data\n│   │   ├── metric-list.go\n│   │   └── type.go\n│   ├── httprqrs\n│   │   └── not-found.go\n│   ├── metric\n│   │   ├── data_manager.go\n│   │   ├── rq_handler.go\n│   │   └── types.go\n│   ├── mw\n│   │   └── handler.go\n│   └── third-party\n│       └── negroni-logrus\n│           ├── LICENSE\n│           └── middleware.go\n└── scripts\n\n````\n\n### How to\n\n######  Step-1 : Build Docker  \n````\nmake docker\n````\n\n######  step-2 : Refer env variables e.g. configure COLLECTION_TIMEOUT in seconds\n\n````\n- SERVER_PORT=9000\n- SERVER_IP_ADDRESS=0.0.0.0\n- HTTP_WRITE_TIMEOUT=15\n- HTTP_READ_TIMEOUT=15\n- HTTP_IDLE_TIMEOUT=60\n- COLLECTION_TIMEOUT=200\n````\n \n######  step-3 : run docker-compose up  \n\nIt will run build image from step-1\n\n######  step-4 - run metric_post.sh from a terminal \n\nRefer demo video \n\n######  step-5 - run metric_get.sh from a terminal \n\nRefer demo video\n\n######  step-6 - run metric_benchmark.sh from a terminal \n\nRefer demo video\n\n#### How To Test \n\n###### Time Window test\n\nRun: ./metric_post.sh \n\nRun: ./metric_get.sh \n\nObserve: metric_post.sh sending one post metric request in every 3 seconds, also \nmetric_get.sh calling get metric request in every 3 seconds.\n\nObserve:  metric_count value in metric_get.sh output :\n\n- It increases based on the configured COLLECTION_TIMEOUT e.g. if configured \n  as 30 seconds then metric_count value will be shown 10 as maximum \n \nStop: metric_post.sh \n\nObserve: metric_count value in metric_get.sh output :\n  \n- It decreases in every 3 seconds and reduced to 0  \n\n###### Concurrency test \n\nRun: ./metric_post.sh ( set each post request to 1 second or remove sleep)\n\nRun: ./metric_benchmark.sh (It sends 2000 with concurrent count as 10 )\n\nObserve: terminal logs \n\n- Everything works as expected\n\n(Refer terminal logs)\n\n\n#### Further work items (not limited to)\n\nIts just a short demo, many further possibilities are with this :\n\n###### \n* Separate http request/response library \n* Separate error related library \n* Various code optimisations \n* Containerize whole thing to docker for testing and implemenation\n* Test cases \n* Validations on reuqest input, and wherever applicable by using e.g. ozzo  \n* Revisit the logical flow and add cases\n* Additional apis\n* Code refactoring \n* Makefile with additional command e.g. docker push to docker\n* Single script to run whole deployment \n* Additional error cases \n* OpenAPI specifications \n* Enhanced Logging \n* Swagger Integrations \n* Connected with Kibana etc for logging\n* ... and so on \n\n###### go, docker, mac os - versions  \n````\n➜  ~ git version\ngit version 2.13.1\n\n➜  ~ docker --version\nDocker version 19.03.8, build afacb8b\n\n➜  ~ make --version \nGNU Make 3.81\nCopyright (C) 2006  Free Software Foundation, Inc.\nThis is free software; see the source for copying conditions.\nThere is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\nPARTICULAR PURPOSE.\n\nThis program built for i386-apple-darwin11.3.0\n\n➜  ~ go version \ngo version go1.16.5 darwin/amd64\n\n➜  ~ uname -a \nDarwin Newyork.local 20.5.0 Darwin Kernel Version 20.5.0: Sat May  8 05:10:33 PDT 2021; root:xnu-7195.121.3~9/RELEASE_X86_64 x86_64\n\n➜  ~ bash --version\nGNU bash, version 3.2.57(1)-release (x86_64-apple-darwin20)\nCopyright (C) 2007 Free Software Foundation, Inc.\n➜  ~ \n\n````\n###### Logs on terminal \n\n###### - Make\n````\n➜  metric-apis git:(main) ✗ make clean\nrm -rf ./dist/*\n➜  metric-apis git:(main) ✗ make build\nrm -rf ./dist\nmkdir dist\nCGO_ENABLED=0 go build -o dist/metric-apis\ncp .env dist/.env\n➜  metric-apis git:(main) ✗ make run\n./dist/metric-apis\nINFO[0000] Config Applied:                              \nINFO[0000] Port:  9000                                  \nINFO[0000] IPAddress:  0.0.0.0                          \nINFO[0000] HTTP WriteTimeout:  15                       \nINFO[0000] HTTP ReadTimeout:  15                        \nINFO[0000] HTTP IdleTimeout:  60                        \nINFO[0000] Collection Timeout:  15                      \nINFO[0000] All configs loaded  \n````\n\n````\n➜  metric-apis git:(main) ✗ make docker\ndocker build -f Dockerfile -t esumit/metric-apis .\nSending build context to Docker daemon  9.963MB\nStep 1/15 : FROM golang:1.12-alpine AS build_base\n ---\u003e 76bddfb5e55e\nStep 2/15 : RUN apk add --no-cache git\n ---\u003e Using cache\n ---\u003e 54d5d5637991\nStep 3/15 : WORKDIR /app\n ---\u003e Using cache\n ---\u003e 604bff6f1803\nStep 4/15 : COPY go.mod ./\n ---\u003e Using cache\n ---\u003e cc8d7841e086\nStep 5/15 : COPY go.sum ./\n ---\u003e Using cache\n ---\u003e f4942387cb49\nStep 6/15 : RUN go mod download\n ---\u003e Using cache\n ---\u003e 11d4051c8ed7\nStep 7/15 : COPY . .\n ---\u003e 03d469381a4c\nStep 8/15 : RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o metric-apis .\n ---\u003e Running in fe343c93ce5f\nRemoving intermediate container fe343c93ce5f\n ---\u003e ced5c61a6bfb\nStep 9/15 : FROM alpine:3.9\n ---\u003e 78a2ce922f86\nStep 10/15 : RUN apk add ca-certificates\n ---\u003e Using cache\n ---\u003e 6d0cc6a42b4b\nStep 11/15 : WORKDIR /root/\n ---\u003e Using cache\n ---\u003e 256d200d3756\nStep 12/15 : COPY --from=build_base /app/metric-apis .\n ---\u003e Using cache\n ---\u003e 5611a00f5c72\nStep 13/15 : COPY --from=build_base /app/.env .\n ---\u003e Using cache\n ---\u003e 26e7cbbbf549\nStep 14/15 : EXPOSE 9000\n ---\u003e Using cache\n ---\u003e 5e036e9ac923\nStep 15/15 : ENTRYPOINT [\"./metric-apis\"]\n ---\u003e Using cache\n ---\u003e 7ddd4e95acdd\nSuccessfully built 7ddd4e95acdd\nSuccessfully tagged esumit/metric-apis:latest\n➜  metric-apis git:(main) ✗ \n````\n\n###### - docker\n\n````\n➜  metric-apis git:(main) ✗ docker run -p 9000:9000 esumit/metric-apis:latest\ntime=\"2021-07-15T00:03:34Z\" level=info msg=\"Config Applied:\"\ntime=\"2021-07-15T00:03:34Z\" level=info msg=\"Port:  9000\"\ntime=\"2021-07-15T00:03:34Z\" level=info msg=\"IPAddress:  0.0.0.0\"\ntime=\"2021-07-15T00:03:34Z\" level=info msg=\"HTTP WriteTimeout:  15\"\ntime=\"2021-07-15T00:03:34Z\" level=info msg=\"HTTP ReadTimeout:  15\"\ntime=\"2021-07-15T00:03:34Z\" level=info msg=\"HTTP IdleTimeout:  60\"\ntime=\"2021-07-15T00:03:34Z\" level=info msg=\"Collection Timeout:  15\"\ntime=\"2021-07-15T00:03:34Z\" level=info msg=\"All configs loaded\"\n````\n\n###### - scripts\n````\n➜  metric-apis git:(main) ✗ docker-compose up --remove-orphan\nRemoving orphan container \"metric-apis_metrics-api_1\"\nStarting metrics-api.local.com ... done\nAttaching to metrics-api.local.com\nmetrics-api.local.com | time=\"2021-07-15T00:07:54Z\" level=info msg=\"Config Applied:\"\nmetrics-api.local.com | time=\"2021-07-15T00:07:54Z\" level=info msg=\"Port:  9000\"\nmetrics-api.local.com | time=\"2021-07-15T00:07:54Z\" level=info msg=\"IPAddress:  0.0.0.0\"\nmetrics-api.local.com | time=\"2021-07-15T00:07:54Z\" level=info msg=\"HTTP WriteTimeout:  15\"\nmetrics-api.local.com | time=\"2021-07-15T00:07:54Z\" level=info msg=\"HTTP ReadTimeout:  15\"\nmetrics-api.local.com | time=\"2021-07-15T00:07:54Z\" level=info msg=\"HTTP IdleTimeout:  60\"\nmetrics-api.local.com | time=\"2021-07-15T00:07:54Z\" level=info msg=\"Collection Timeout:  200\"\nmetrics-api.local.com | time=\"2021-07-15T00:07:54Z\" level=info msg=\"All configs loaded\"\n````\n\n````\n➜  metric-apis git:(main) ✗ ./metric_post.sh \n\nMetric Logging : 1 \nPress [CTRL+C] to stop..\n-----------------------------------------------\n\nPOST \u003e\u003e\u003e\nURL: http://localhost:9000/metrics/active_visitors\n\n{ \"value\": 6}\n\nResponse:\n\n { \"metric_id\": \"ad169b41-4845-46d2-a404-9229f1b6a0f5\" }\n\nMetric Logging : 2 \nPress [CTRL+C] to stop..\n-----------------------------------------------\n\nPOST \u003e\u003e\u003e\nURL: http://localhost:9000/metrics/active_visitors\n\n{ \"value\": 19}\n\nResponse:\n\n { \"metric_id\": \"e95d2668-75d2-44aa-bb30-8e450009c0a0\" }\n````\n\n````\n➜  metric-apis git:(main) ✗ ./metric_get.sh \n\nMetric Reporting : 1 \nPress [CTRL+C] to stop..\n-----------------------------------------------\n\nGET \u003c\u003c\u003c\nURL: http://localhost:9000/metrics/active_visitors/sum\n\n\nResponse:\n\n { \"start_time\": \"2021-07-15 00:05:49\", \"end_time\": \"2021-07-15 00:09:09\", \"metric_count\": 10, \"metric_key\": \"active_visitors\", \"metric_sum\": 111 }\n\nMetric Reporting : 2 \nPress [CTRL+C] to stop..\n-----------------------------------------------\n\nGET \u003c\u003c\u003c\nURL: http://localhost:9000/metrics/active_visitors/sum\n\n\nResponse:\n\n { \"start_time\": \"2021-07-15 00:05:52\", \"end_time\": \"2021-07-15 00:09:12\", \"metric_count\": 11, \"metric_key\": \"active_visitors\", \"metric_sum\": 118 }\n\nMetric Reporting : 3 \nPress [CTRL+C] to stop..\n-----------------------------------------------\n\nGET \u003c\u003c\u003c\nURL: http://localhost:9000/metrics/active_visitors/sum\n\n\nResponse:\n\n { \"start_time\": \"2021-07-15 00:05:55\", \"end_time\": \"2021-07-15 00:09:15\", \"metric_count\": 12, \"metric_key\": \"active_visitors\", \"metric_sum\": 136 }\n\n````\n\n````\n➜  metric-apis git:(main) ✗ ab -n 20000 -c 100 \"127.0.0.1:9000/active_visitors/sum\"\nThis is ApacheBench, Version 2.3 \u003c$Revision: 1879490 $\u003e\nCopyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/\nLicensed to The Apache Software Foundation, http://www.apache.org/\n\nBenchmarking 127.0.0.1 (be patient)\nCompleted 2000 requests\nCompleted 4000 requests\nCompleted 6000 requests\nCompleted 8000 requests\nCompleted 10000 requests\nCompleted 12000 requests\nCompleted 14000 requests\nCompleted 16000 requests\nCompleted 18000 requests\nCompleted 20000 requests\nFinished 20000 requests\n\n\nServer Software:        \nServer Hostname:        127.0.0.1\nServer Port:            9000\n\nDocument Path:          /active_visitors/sum\nDocument Length:        51 bytes\n\nConcurrency Level:      100\nTime taken for tests:   38.532 seconds\nComplete requests:      20000\nFailed requests:        0\nNon-2xx responses:      20000\nTotal transferred:      4540000 bytes\nHTML transferred:       1020000 bytes\nRequests per second:    519.05 [#/sec] (mean)\nTime per request:       192.661 [ms] (mean)\nTime per request:       1.927 [ms] (mean, across all concurrent requests)\nTransfer rate:          115.06 [Kbytes/sec] received\n\nConnection Times (ms)\n              min  mean[+/-sd] median   max\nConnect:        0  102 1288.2      1   20116\nProcessing:     2   90  64.0     88    1016\nWaiting:        2   88  62.7     86    1016\nTotal:          3  192 1287.3     91   20238\n\nPercentage of the requests served within a certain time (ms)\n  50%     91\n  66%    105\n  75%    114\n  80%    120\n  90%    136\n  95%    154\n  98%    191\n  99%    964\n 100%  20238 (longest request)\n➜  metric-apis git:(main) ✗ \n````\n\n````\n➜  metric-apis git:(main) ✗ ./metric_benchmark.sh \n\nab -n 2000 -c 10 'localhost:9000/active_visitors/sum'\nGET \u003c\u003c\u003c\nURL: http://localhost:9000/metrics/'active_visitors'/sum\n\nCompleted 200 requests\nCompleted 400 requests\nCompleted 600 requests\nCompleted 800 requests\nCompleted 1000 requests\nCompleted 1200 requests\nCompleted 1400 requests\nCompleted 1600 requests\nCompleted 1800 requests\nCompleted 2000 requests\nFinished 2000 requests\n\n\nThis is ApacheBench, Version 2.3 \u003c$Revision: 1879490 $\u003e Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking localhost (be patient) Server Software: Server Hostname: localhost Server Port: 9000 Document Path: /active_visitors/sum Document Length: 51 bytes Concurrency Level: 10 Time taken for tests: 3.329 seconds Complete requests: 2000 Failed requests: 0 Non-2xx responses: 2000 Total transferred: 454000 bytes HTML transferred: 102000 bytes Requests per second: 600.81 [#/sec] (mean) Time per request: 16.644 [ms] (mean) Time per request: 1.664 [ms] (mean, across all concurrent requests) Transfer rate: 133.19 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 1 3.1 0 139 Processing: 3 16 13.5 14 163 Waiting: 3 15 12.9 14 163 Total: 3 16 13.8 15 164 Percentage of the requests served within a certain time (ms) 50% 15 66% 17 75% 19 80% 20 90% 22 95% 25 98% 36 99% 95 100% 164 (longest request)\n➜  metric-apis git:(main) ✗ \n````","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fesumit%2Fmetric-apis","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fesumit%2Fmetric-apis","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fesumit%2Fmetric-apis/lists"}