module/apmazure/blob.go (144 lines of code) (raw):

// Licensed to Elasticsearch B.V. under one or more contributor // license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright // ownership. Elasticsearch B.V. licenses this file to you under // the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package apmazure // import "go.elastic.co/apm/module/apmazure/v2" import ( "fmt" "net/http" "net/url" "strings" "github.com/Azure/azure-pipeline-go/pipeline" ) type blobRPC struct { accountName string resourceName string req pipeline.Request } func (b *blobRPC) name() string { return fmt.Sprintf("AzureBlob %s %s", b.operation(), b.resourceName) } func (b *blobRPC) _type() string { return "storage" } func (b *blobRPC) subtype() string { return "azureblob" } func (b *blobRPC) targetName() string { return "" } func (b *blobRPC) storageAccountName() string { return b.accountName } func (b *blobRPC) resource() string { return b.resourceName } func (b *blobRPC) operation() string { if b.req.Method == http.MethodDelete { return "Delete" } q := b.req.URL.Query() switch b.req.Method { // From net/http documentation: // For client requests, an empty string means GET. case http.MethodGet, "": return b.getOperation(q) case http.MethodPost: return b.postOperation(q) case http.MethodHead: return b.headOperation(q) case http.MethodPut: return b.putOperation(q, b.req.Header) default: return b.req.Method } } func (b *blobRPC) getOperation(v url.Values) string { restype := v.Get("restype") comp := v.Get("comp") if (restype == "" && comp == "") || comp == "blocklist" { return "Download" } if restype == "container" && comp == "" { return "GetProperties" } switch comp { case "metadata": return "GetMetadata" case "acl": return "GetAcl" case "list": if restype == "container" { return "ListBlobs" } return "ListContainers" case "tags": if v.Get("where") != "" { return "FindTags" } return "GetTags" default: return "unknown operation" } } func (b *blobRPC) postOperation(v url.Values) string { comp := v.Get("comp") switch comp { case "batch": return "Batch" case "query": return "Query" case "userdelegationkey": return "GetUserDelegationKey" default: return "unknown operation" } } func (b *blobRPC) headOperation(v url.Values) string { restype := v.Get("restype") comp := v.Get("comp") if restype == "" && comp == "" { return "GetProperties" } if restype != "container" { return "unknown operation" } switch comp { case "metadata": return "GetMetadata" case "acl": return "GetAcl" default: return "unknown operation" } } func (b *blobRPC) putOperation(v url.Values, h http.Header) string { // header.Get canonicalizes the key, ie. x-ms-copy-source->X-Ms-Copy-Source. // The headers used are all lowercase, so we access the map directly. _, copySource := h["x-ms-copy-source"] _, blobType := h["x-ms-blob-type"] _, pageWrite := h["x-ms-page-write"] restype := v.Get("restype") comp := v.Get("comp") if restype == "container" && comp == "acl" { return "SetAcl" } if comp == "" && !(copySource || blobType || pageWrite) { return "Create" } if copySource { return "Copy" } if blobType { return "Upload" } if comp == "page" && pageWrite { return "Clear" } switch comp { case "block", "blocklist", "page", "appendblock": return "Upload" case "copy": return "Abort" case "metadata": return "SetMetadata" case "lease", "snapshot", "undelete", "seal", "rename": return strings.Title(comp) case "properties", "tags", "tier", "expiry": return "Set" + strings.Title(comp) default: return "unknown operation" } }