{"id":13514167,"url":"https://github.com/thundra-io/thundra-lambda-agent-go","last_synced_at":"2025-03-31T02:33:30.186Z","repository":{"id":29507786,"uuid":"121881137","full_name":"thundra-io/thundra-lambda-agent-go","owner":"thundra-io","description":"Thundra Lambda Go Agent","archived":true,"fork":false,"pushed_at":"2022-03-09T11:42:38.000Z","size":2197,"stargazers_count":20,"open_issues_count":2,"forks_count":1,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-11-01T17:39:47.714Z","etag":null,"topics":["async-monitoring","aws","aws-lambda","distributed-tracing","go","golang","instrumentation","logging","metric","monitoring","serverless","thundra","tracing"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thundra-io.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":"CODEOWNERS","security":null,"support":null}},"created_at":"2018-02-17T18:30:02.000Z","updated_at":"2023-07-31T12:04:25.000Z","dependencies_parsed_at":"2022-08-07T14:30:17.457Z","dependency_job_id":null,"html_url":"https://github.com/thundra-io/thundra-lambda-agent-go","commit_stats":null,"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thundra-io%2Fthundra-lambda-agent-go","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thundra-io%2Fthundra-lambda-agent-go/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thundra-io%2Fthundra-lambda-agent-go/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thundra-io%2Fthundra-lambda-agent-go/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thundra-io","download_url":"https://codeload.github.com/thundra-io/thundra-lambda-agent-go/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246407403,"owners_count":20772127,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["async-monitoring","aws","aws-lambda","distributed-tracing","go","golang","instrumentation","logging","metric","monitoring","serverless","thundra","tracing"],"created_at":"2024-08-01T05:00:48.386Z","updated_at":"2025-03-31T02:33:25.175Z","avatar_url":"https://github.com/thundra-io.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# Lambda Go Agent [![OpenTracing Badge](https://img.shields.io/badge/OpenTracing-enabled-blue.svg)](http://opentracing.io) [![Thundra CI Check](https://github.com/thundra-io/thundra-lambda-agent-go/actions/workflows/build.yml/badge.svg)](https://github.com/thundra-io/thundra-lambda-agent-go/actions/workflows/build.yml) [![Go Report Card](https://goreportcard.com/badge/github.com/thundra-io/thundra-lambda-agent-go)](https://goreportcard.com/report/github.com/thundra-io/thundra-lambda-agent-go)\n\nTrace your AWS lambda functions with async monitoring by [Thundra](https://www.thundra.io/)!\n\nCheck out [Thundra docs](https://apm.docs.thundra.io) for more information.\n\n### Usage\n\nIn order to trace your lambda usages with Thundra all you need to do is wrap your function.\n\n```go\nimport \"github.com/thundra-io/thundra-lambda-agent-go/v2/thundra\"\t// with go modules enabled (GO111MODULE=on or outside GOPATH) for version \u003e= v2.3.1\nimport \"github.com/thundra-io/thundra-lambda-agent-go/thundra\"         // with go modules disabled\n```\n\n```go\npackage main\n\nimport (\n\t\"github.com/aws/aws-lambda-go/lambda\"\n\t// thundra go agent import here\n)\n\n// Your lambda handler\nfunc handler() (string, error) {\n\treturn \"Hello, Thundra!\", nil\n}\n\nfunc main() {\n\t// Wrap your lambda handler with Thundra\n\tlambda.Start(thundra.Wrap(handler))\n}\n```\n\nLater just build and deploy your executable to AWS as regular. Test your function on lambda console and visit [Thundra](https://console.thundra.io/) to observe your function metrics.\n\n#### Environment variables\n\n| Name                                                  |  Type  |       Default Value       |\n| :---------------------------------------------------- | :----: | :-----------------------: |\n| thundra_applicationProfile                            | string |          default          |\n| thundra_agent_lambda_disable                          |  bool  |           false           |\n| thundra_agent_lambda_timeout_margin                   | number |            200            |\n| thundra_agent_lambda_report_rest_baseUrl              | string | https://api.thundra.io/v1 |\n| thundra_agent_lambda_trace_disable                    |  bool  |           false           |\n| thundra_agent_lambda_metric_disable                   |  bool  |           false           |\n| thundra_agent_lambda_log_disable                      |  bool  |           false           |\n| thundra_log_logLevel                                  | string |           TRACE           |\n| thundra_agent_lambda_trace_request_skip               |  bool  |           false           |\n| thundra_agent_lambda_trace_response_skip              |  bool  |           false           |\n| thundra_agent_lambda_report_rest_trustAllCertificates |  bool  |           false           |\n| thundra_agent_lambda_debug_enable                     |  bool  |           false           |\n| thundra_agent_lambda_warmup_warmupAware               |  bool  |           false           |\n\n### Async Monitoring\n\nCheck out our [docs](https://docs.thundra.io/docs/how-to-setup-async-monitoring) to see how to configure Thundra and async monitoring to visualize your functions in [Thundra](https://www.thundra.io/).\n\n## Warmup Support\n\nYou can cut down cold starts easily by deploying our lambda function [`thundra-lambda-warmup`](https://github.com/thundra-io/thundra-lambda-warmup).\n\nOur agent handles warmup requests automatically so you don't need to make any code changes.\n\nYou just need to deploy `thundra-lambda-warmup` once, then you can enable warming up for your lambda by\n\n- setting its environment variable `thundra_agent_lambda_warmup_warmupAware` **true** OR\n- adding its name to `thundra-lambda-warmup`'s environment variable `thundra_lambda_warmup_function`.\n\nCheck out [this part](https://thundra.readme.io/docs/how-to-warmup) in our docs for more information.\n\n## Thundra Go Agent Integrations\n\n### AWS SDK\n\nThundra's Go agent provides you with the capability to trace AWS SDK by wrapping the session object that AWS SDK provides.\nYou can easily start using it by simply wrapping your session objects as shown in the following code:\n\n```go\npackage main\n\nimport (\n\t\"github.com/aws/aws-lambda-go/lambda\"\n\t\"github.com/aws/aws-sdk-go/aws\"\n\t\"github.com/aws/aws-sdk-go/aws/session\"\n\t\"github.com/aws/aws-sdk-go/service/dynamodb\"\n\t\"github.com/thundra-io/thundra-lambda-agent-go/thundra\"\n\tthundraaws \"github.com/thundra-io/thundra-lambda-agent-go/wrappers/aws\"\n)\n\n// Your lambda handler\nfunc handler() (string, error) {\n\t// Create a new session object\n\tsess, _ := session.NewSession(\u0026aws.Config{\n\t\tRegion: aws.String(\"us-west-2\")},\n\t)\n\n\t// Wrap it using the thundraaws.Wrap method\n\tsess = thundraaws.Wrap(sess)\n\n\t// Create a new client using the wrapped session\n\tsvc := dynamodb.New(sess)\n\n\t// Use the client as normal, Thundra will automatically\n\t// create spans for the AWS SDK calls\n\tsvc.PutItem(\u0026dynamodb.PutItemInput{\n\t\tItem: map[string]*dynamodb.AttributeValue{\n\t\t\t\"AlbumTitle\": {\n\t\t\t\tS: aws.String(\"Somewhat Famous\"),\n\t\t\t},\n\t\t\t\"Artist\": {\n\t\t\t\tS: aws.String(\"No One You Know\"),\n\t\t\t},\n\t\t\t\"SongTitle\": {\n\t\t\t\tS: aws.String(\"Call Me Today\"),\n\t\t\t},\n\t\t},\n\t\tReturnConsumedCapacity: aws.String(\"TOTAL\"),\n\t\tTableName:              aws.String(\"Music\"),\n\t})\n\n\treturn \"Hello, Thundra!\", nil\n}\n\nfunc main() {\n\t// Wrap your lambda handler with Thundra\n\tlambda.Start(thundra.Wrap(handler))\n}\n```\n\n### Mongo SDK\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\n\t\"github.com/aws/aws-lambda-go/events\"\n\t\"github.com/aws/aws-lambda-go/lambda\"\n\t\"github.com/thundra-io/thundra-lambda-agent-go/thundra\"\n\tthundramongo \"github.com/thundra-io/thundra-lambda-agent-go/wrappers/mongodb\"\n\t\"go.mongodb.org/mongo-driver/mongo\"\n\t\"go.mongodb.org/mongo-driver/mongo/options\"\n)\n\ntype Post struct {\n\tAuthor string\n\tText   string\n}\n\nfunc handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {\n\n\tclient, _ := mongo.Connect(context.Background(), options.Client().ApplyURI(\"mongodb://localhost:27017\").SetMonitor(thundramongo.NewCommandMonitor()))\n\n\tcollection := client.Database(\"test\").Collection(\"posts\")\n\tpost := Post{\"Mike\", \"My first blog!\"}\n\n\t// Insert post to mongodb\n\tcollection.InsertOne(context.TODO(), post)\n\n\treturn events.APIGatewayProxyResponse{\n\t\tBody:       \"res\",\n\t\tStatusCode: 200,\n\t}, nil\n}\n\nfunc main() {\n\tlambda.Start(thundra.Wrap(handler))\n}\n```\n\n### Mysql SDK\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\n\t\"github.com/aws/aws-lambda-go/lambda\"\n\t\"github.com/go-sql-driver/mysql\"\n\t\"github.com/thundra-io/thundra-lambda-agent-go/thundra\"\n\tthundrardb \"github.com/thundra-io/thundra-lambda-agent-go/wrappers/rdb\"\n)\n\nfunc handler(ctx context.Context) {\n\n\t// Register wrapped driver for tracing\n\t// Note that driver name registered should be different than \"mysql\" as it is already registered on init method of\n\t// this package otherwise it panics.\n\tsql.Register(\"thundra-mysql\", thundrardb.Wrap(\u0026mysql.MySQLDriver{}))\n\n\t// Get the database handle with registered driver name\n\tdb, err := sql.Open(\"thundra-mysql\", \"user:userpass@tcp(docker.for.mac.localhost:3306)/db\")\n\n\tif err != nil {\n\t\t// Just for example purpose. You should use proper error handling instead of panic\n\t\tpanic(err.Error())\n\t}\n\tdefer db.Close()\n\n\trows, err := db.Query(\"SELECT * FROM test\")\n\tif err != nil {\n\t\tthundra.Logger.Error(err)\n\t}\n\tdefer rows.Close()\n}\n\nfunc main() {\n\tlambda.Start(thundra.Wrap(handler))\n}\n```\n\n### PostgreSQL SDK\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\n\t\"github.com/aws/aws-lambda-go/lambda\"\n\t\"github.com/lib/pq\"\n\t\"github.com/thundra-io/thundra-lambda-agent-go/thundra\"\n\tthundrardb \"github.com/thundra-io/thundra-lambda-agent-go/wrappers/rdb\"\n)\n\nfunc handler(ctx context.Context) {\n\t// Register wrapped driver for tracing\n\t// Note that driver name registered should be different than \"postgres\"\n\t// as it is already registered on init method of this package\n\t// otherwise it panics.\n\tsql.Register(\"thundra-postgres\", thundrardb.Wrap(\u0026pq.Driver{}))\n\n\t// Get the database handle with registered driver name\n\tdb, err := sql.Open(\"thundra-postgres\", \"postgres://user:userpass@docker.for.mac.localhost:5432/db?sslmode=disable\")\n\n\t_, err = db.Exec(\"CREATE table IF NOT EXISTS test(id int, type text)\")\n\n\tif err != nil {\n\t\t// Just for example purpose. You should use proper error handling instead of panic\n\t\tpanic(err.Error())\n\t}\n\tdefer db.Close()\n\n\t// Perform a query\n\trows, err := db.Query(\"SELECT * FROM test\")\n\tif err != nil {\n\t\tthundra.Logger.Error(err)\n\t}\n\tdefer rows.Close()\n}\n\nfunc main() {\n\tlambda.Start(thundra.Wrap(handler))\n}\n\n```\n\n### Redis SDK\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/aws/aws-lambda-go/lambda\"\n\t\"github.com/thundra-io/thundra-lambda-agent-go/thundra\"\n\tthundraredigo \"github.com/thundra-io/thundra-lambda-agent-go/wrappers/redis/redigo\"\n)\n\nfunc test() {\n\tconn, err := thundraredigo.Dial(\"tcp\", \"docker.for.mac.localhost:6379\")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tdefer conn.Close()\n\n\tret, _ := conn.Do(\"SET\", \"mykey\", \"hello\")\n\tfmt.Printf(\"%s\\n\", ret)\n\n\tret, _ = conn.Do(\"GET\", \"mykey\")\n\tfmt.Printf(\"%s\\n\", ret)\n\n}\n\nfunc main() {\n\tlambda.Start(thundra.Wrap(test))\n}\n```\n\n### Http SDK\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\n\t\"github.com/aws/aws-lambda-go/events\"\n\t\"github.com/aws/aws-lambda-go/lambda\"\n\t\"github.com/thundra-io/thundra-lambda-agent-go/thundra\"\n\tthundrahttp \"github.com/thundra-io/thundra-lambda-agent-go/wrappers/http\"\n)\n\nfunc handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {\n\n\tthundraHttpClient := thundrahttp.Wrap(http.Client{})\n\n\tresp, err := thundraHttpClient.Get(\"URL\")\n\tif err == nil {\n\t\tfmt.Println(resp)\n\t}\n\tfmt.Println(err)\n\n\treturn events.APIGatewayProxyResponse{\n\t\tBody:       \"res\",\n\t\tStatusCode: 200,\n\t}, nil\n}\n\nfunc main() {\n\tlambda.Start(thundra.Wrap(handler))\n}\n```\n\n### Elasticsearch SDK\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"reflect\"\n\n\t\"github.com/aws/aws-lambda-go/lambda\"\n\t\"github.com/thundra-io/thundra-lambda-agent-go/thundra\"\n\tthundraelastic \"github.com/thundra-io/thundra-lambda-agent-go/wrappers/elastic/olivere\"\n\t\"gopkg.in/olivere/elastic.v6\"\n)\n\nfunc getClient() *elastic.Client {\n\n\tvar httpClient = thundraelastic.Wrap(\u0026http.Client{})\n\tvar client, _ = elastic.NewClient(\n\t\telastic.SetURL(\"http://localhost:9200\"),\n\t\telastic.SetHttpClient(httpClient),\n\t\telastic.SetSniff(false),\n\t\telastic.SetHealthcheck(false),\n\t)\n\treturn client\n}\n\n// Tweet is a structure used for serializing/deserializing data in Elasticsearch.\ntype Tweet struct {\n\tUser     string   `json:\"user\"`\n\tMessage  string   `json:\"message\"`\n\tRetweets int      `json:\"retweets\"`\n\tImage    string   `json:\"image,omitempty\"`\n\tTags     []string `json:\"tags,omitempty\"`\n\tLocation string   `json:\"location,omitempty\"`\n}\n\nfunc handler() {\n\n\t// Starting with elastic.v5, you must pass a context to execute each service\n\tctx := context.Background()\n\n\t// Obtain a client and connect to the default Elasticsearch installation\n\t// on 127.0.0.1:9200. Of course you can configure your client to connect\n\t// to other hosts and configure it in various other ways.\n\tclient := getClient()\n\n\t// Index a tweet (using JSON serialization)\n\ttweet1 := Tweet{User: \"olivere\", Message: \"Take Five\", Retweets: 0}\n\tput1, err := client.Index().\n\t\tIndex(\"thundra\").\n\t\tType(\"users\").\n\t\tId(\"id\").\n\t\tBodyJson(tweet1).\n\t\tDo(ctx)\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\tfmt.Printf(\"Indexed tweet %s to index %s, type %s\\n\", put1.Id, put1.Index, put1.Type)\n\n\t// Get tweet with specified ID\n\tget1, err := client.Get().\n\t\tIndex(\"twitter\").\n\t\tType(\"tweet\").\n\t\tId(\"1\").\n\t\tDo(ctx)\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\tif get1.Found {\n\t\tfmt.Printf(\"Got document %s in version %d from index %s, type %s\\n\", get1.Id, get1.Version, get1.Index, get1.Type)\n\t}\n\n\t// Flush to make sure the documents got written.\n\t_, err = client.Flush().Index(\"twitter\").Do(ctx)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Search with a term query\n\ttermQuery := elastic.NewTermQuery(\"user\", \"olivere\")\n\tsearchResult, err := client.Search().\n\t\tIndex(\"twitter\").   // search in index \"twitter\"\n\t\tQuery(termQuery).   // specify the query\n\t\tSort(\"user\", true). // sort by \"user\" field, ascending\n\t\tFrom(0).Size(10).   // take documents 0-9\n\t\tPretty(true).       // pretty print request and response JSON\n\t\tDo(ctx)             // execute\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\n}\n\nfunc main() {\n\tlambda.Start(thundra.Wrap(handler))\n}\n```\n\n# Setting up local development environment\n\n1. Clone Go sample lambda app to your local\n\n```sh\ngit clone https://github.com/thundra-io/thundra-go-lambda-sample-app.git\n\n# cd into sample app\n\ncd thundra-go-lambda-sample-app\n```\n\n2. Inside of sample app root directory, clone Thundra Go agent. The sample app has configured the way that it will ignore local Thundra Go agent for git and local version changes of Thundra agent will be effective.\n\n```sh\ngit clone https://github.com/thundra-io/thundra-lambda-agent-go.git\n```\n\n3. In serverless.yml in project root directory, **uncomment** thundra_apiKey and **put your Thundra api key value**, which you can get from apm.thundra.io\n\nCurrent serverless.yml\n\n```yml\n#thundra_apiKey: \u003cyour_thundra_ApiKey\u003e\n```\n\nShould look something like this\n\n```yml\nthundra_apiKey: \u003cyour_project_key_from_thundra\u003e\n```\n\n4. Configure your sls\n\n```sh\nsls\n```\n\n5. Deploy your lambda to AWS. Thundra Go lambda agent's codebase, which is going to used for sending instrumentation data to apm.thundra.io, will be your own copy at your local.\n\n```sh\nsls deploy\n```\n\n6. Trigger the lambda endpoint and monitor your sample app in apm.thundra.io !\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthundra-io%2Fthundra-lambda-agent-go","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthundra-io%2Fthundra-lambda-agent-go","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthundra-io%2Fthundra-lambda-agent-go/lists"}