{"id":23895500,"url":"https://github.com/michimani/evidently-local","last_synced_at":"2026-03-10T10:30:55.765Z","repository":{"id":176717595,"uuid":"657919721","full_name":"michimani/evidently-local","owner":"michimani","description":"This is a simple http server to manage feature flags, compatible with Amazon CloudWatch Evidently.","archived":false,"fork":false,"pushed_at":"2024-09-08T15:14:15.000Z","size":53,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-09-10T04:57:45.441Z","etag":null,"topics":["aws","evidently"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/michimani.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-06-24T08:00:47.000Z","updated_at":"2024-09-08T15:14:12.000Z","dependencies_parsed_at":"2024-09-08T17:00:52.934Z","dependency_job_id":"974cbe20-47a5-49de-bc4b-ae24382a9ac6","html_url":"https://github.com/michimani/evidently-local","commit_stats":null,"previous_names":["michimani/evidently-local"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/michimani/evidently-local","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michimani%2Fevidently-local","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michimani%2Fevidently-local/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michimani%2Fevidently-local/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michimani%2Fevidently-local/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/michimani","download_url":"https://codeload.github.com/michimani/evidently-local/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michimani%2Fevidently-local/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30330507,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T05:25:20.737Z","status":"ssl_error","status_checked_at":"2026-03-10T05:25:17.430Z","response_time":106,"last_error":"SSL_read: 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":["aws","evidently"],"created_at":"2025-01-04T15:57:31.240Z","updated_at":"2026-03-10T10:30:55.732Z","avatar_url":"https://github.com/michimani.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"Evidently-Local\n===\n\n[![codecov](https://codecov.io/gh/michimani/evidently-local/branch/main/graph/badge.svg?token=YJIO3RF9ZR)](https://codecov.io/gh/michimani/evidently-local)\n\nThis is a simple http server to manage feature flags, compatible with Amazon CloudWatch Evidently.\n\n# Supported Evidently Action\n\n[Actions - CloudWatch Evidently](https://docs.aws.amazon.com/cloudwatchevidently/latest/APIReference/API_Operations.html)\n\n- [EvaluateFeature](https://docs.aws.amazon.com/cloudwatchevidently/latest/APIReference/API_EvaluateFeature.html)\n  - Only support evaluation with default variation and override rules.\n  - TODO: Evaluation with some launches.\n- [BatchEvaluateFeature](https://docs.aws.amazon.com/cloudwatchevidently/latest/APIReference/API_BatchEvaluateFeature.html)\n  - Only support evaluation with default variation and override rules.\n  - TODO: Evaluation with some launches.\n\n# Usage\n\n## Simple usage\n\n### 1. Create JSON files that defines the Project and Feature.\n\nFirst, create a JSON file that defines the Project and Feature in the following configuration.\n\n```text\ndata\n└── projects\n    └── test-project\n        └── features\n            ├── test-feature-1.json\n            └── test-feature-2.json\n```\n\nIn this case, project name is **test-project** and features that belong to the project are **test-feature-1** and **test-feature-2**.\n\nAnd `test-feature-1.json` is like this.\n\n```json\n{\n  \"defaultVariation\": \"False\",\n  \"entityOverrides\": {\n    \"force-true\": \"True\"\n  },\n  \"name\": \"test-feature-1\",\n  \"project\": \"test-project\",\n  \"valueType\": \"BOOLEAN\",\n  \"variations\": [\n    {\n      \"name\": \"True\",\n      \"value\": {\n        \"boolValue\": true\n      }\n    },\n    {\n      \"name\": \"False\",\n      \"value\": {\n        \"boolValue\": false\n      }\n    }\n  ]\n}\n```\n\nIn this case, `test-feature-1` is a Feature that returns a boolean that belongs to `test-project`, and the default Variation is `False`. Also, an override rule is set to always return `True` for the EntityID `force-true`.\n\n\nThis JSON file has the same structure as the JSON that can be obtained with the GetFeature API. So, if you want to reproduce the Feature that already exists on AWS locally, you can use the JSON obtained with the following AWS CLI command as it is.\n\n```bash\naws evidently get-feature \\\n--project-name 'test-project' \\\n--feature-name 'test-feature-1' \\\n--query 'feature'\n--output json \\\n\u003e test-feature-1.json\n```\n\n### 2. Create a Dockerfile and run Evidently-Local\n\nSecond, create a `Dockerfile` to run Evidently-Local server. The following is an example of `Dockerfile`.\n\n```dockerfile\nFROM golang:1.21-alpine3.18 AS builder\n\nWORKDIR /app\n\nADD https://github.com/michimani/evidently-local/archive/refs/tags/v0.0.4.zip ./\n\nRUN unzip v0.0.4.zip \\\n  \u0026\u0026 cd evidently-local-0.0.4 \\\n  \u0026\u0026 go install \\\n  \u0026\u0026 go build -o evidently-local . \\\n  \u0026\u0026 mv evidently-local /app\n\n# for run stage\nFROM alpine:3.18.2\n\nWORKDIR /app\n\nCOPY --from=builder /app/evidently-local .\n\nRUN mkdir data\n\n# from your local data directory\nADD ./testdata ./data\n\nEXPOSE 2306\n\nCMD [ \"/app/evidently-local\" ]\n```\n\nThen build image and run container.\n\n```bash\ndocker build -t evidently-local . \\\n\u0026\u0026 docker run  -p 2306:2306 evidently-local:latest\n```\n\n### 3. Call EvaluateFeature API\n\nFinally, call EvaluateFeature API using AWS SDK for each language. The following is an example of calling the API using Go SDK.\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"reflect\"\n\n\t\"github.com/gofrs/uuid\"\n\n\t\"github.com/aws/aws-sdk-go-v2/aws\"\n\t\"github.com/aws/aws-sdk-go-v2/config\"\n\t\"github.com/aws/aws-sdk-go-v2/service/evidently\"\n\t\"github.com/aws/aws-sdk-go-v2/service/evidently/types\"\n)\n\nconst (\n\tevidentlyEndpointURLKey = \"EVIDENTLY_ENDPOINT_URL\"\n\tproject                 = \"test-project\"\n\tfeature                 = \"test-feature-1\"\n\tregion                  = \"ap-northeast-1\"\n)\n\nfunc main() {\n\tclient, err := createEvidentlyClient()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tuuid, err := uuid.NewV4()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tentityID := uuid.String()\n\n\targs := os.Args\n\tif len(args) \u003e 1 {\n\t\tentityID = args[1]\n\t}\n\n\tevaluateFeature(client, project, feature, entityID)\n}\n\nfunc evaluateFeature(client *evidently.Client, project, feature, entityID string) {\n\tout, err := client.EvaluateFeature(context.Background(), \u0026evidently.EvaluateFeatureInput{\n\t\tProject:  aws.String(project),\n\t\tFeature:  aws.String(feature),\n\t\tEntityId: aws.String(entityID),\n\t})\n\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Printf(\"EntityID: %s\\n\", entityID)\n\tfmt.Printf(\"Reason: %s\\n\", aws.ToString(out.Reason))\n\tfmt.Printf(\"Variation: %s\\n\", aws.ToString(out.Variation))\n\tfmt.Printf(\"Type of Value: %s\\n\", reflect.TypeOf(out.Value))\n\n\tvar value any\n\tswitch out.Value.(type) {\n\tcase *types.VariableValueMemberStringValue:\n\t\tvalue = out.Value.(*types.VariableValueMemberStringValue).Value\n\tcase *types.VariableValueMemberBoolValue:\n\t\tvalue = out.Value.(*types.VariableValueMemberBoolValue).Value\n\tcase *types.VariableValueMemberLongValue:\n\t\tvalue = out.Value.(*types.VariableValueMemberLongValue).Value\n\tcase *types.VariableValueMemberDoubleValue:\n\t\tvalue = out.Value.(*types.VariableValueMemberDoubleValue).Value\n\tdefault:\n\t\t// noop\n\t}\n\n\tfmt.Printf(\"Value: %+v\\n\", value)\n}\n\nfunc createEvidentlyClient() (*evidently.Client, error) {\n\tevidentlyEndpointURL := os.Getenv(evidentlyEndpointURLKey)\n\tif len(evidentlyEndpointURL) == 0 {\n\t\tcfg, err := config.LoadDefaultConfig(context.Background(),\n\t\t\tconfig.WithRegion(region),\n\t\t)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tc := evidently.NewFromConfig(cfg)\n\t\treturn c, nil\n\t}\n\n\t// create client for custom endpoint\n\tcustomEndpointResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, opts ...any) (aws.Endpoint, error) {\n\t\treturn aws.Endpoint{\n\t\t\tURL:               evidentlyEndpointURL,\n\t\t\tHostnameImmutable: true,\n\t\t}, nil\n\t})\n\n\tcfg, err := config.LoadDefaultConfig(context.Background(),\n\t\tconfig.WithRegion(region),\n\t\tconfig.WithEndpointResolverWithOptions(customEndpointResolver),\n\t)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tc := evidently.NewFromConfig(cfg)\n\treturn c, nil\n}\n```\n\nRun this script with the following command.\n\n```bash\nEVIDENTLY_ENDPOINT_URL='http://localhost:2306' go run .\n```\n\nThen you will get the following result.\n\n```text\nEntityID: 4eb2759a-c96b-43b3-acf2-25c669ab280b\nReason: DEFAULT (local)\nVariation: False\nType of Value: *types.VariableValueMemberBoolValue\nValue: false\n```\n\nAlso, if you run it as follows, you will get the result of the override rule.\n\n```bash\nEVIDENTLY_ENDPOINT_URL='http://localhost:2306' go run . 'force-true'\n```\n\n```text\nEntityID: force-true\nReason: OVERRIDE_RULE (local)\nVariation: True\nType of Value: *types.VariableValueMemberBoolValue\nValue: true\n```\n\n\n# License\n\n[MIT](./LICENSE)\n\n# Author\n\n[michimani210](https://twitter.com/michimani210)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichimani%2Fevidently-local","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmichimani%2Fevidently-local","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichimani%2Fevidently-local/lists"}