diff --git a/monitoring/add-metrics/Dockerfile b/monitoring/add-metrics/Dockerfile new file mode 100644 index 00000000..05dd54a2 --- /dev/null +++ b/monitoring/add-metrics/Dockerfile @@ -0,0 +1,17 @@ +# Используем Python как базовый образ +FROM python:3.10-slim + +# Устанавливаем рабочую директорию +WORKDIR /app + +# Копируем файлы проекта +COPY . /app + +# Устанавливаем зависимости +RUN pip install --no-cache-dir -r requirements.txt + +# Открываем порт для работы API +EXPOSE 8000 + +# Запускаем приложение +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/monitoring/add-metrics/__pycache__/main.cpython-310.pyc b/monitoring/add-metrics/__pycache__/main.cpython-310.pyc new file mode 100644 index 00000000..98658c48 Binary files /dev/null and b/monitoring/add-metrics/__pycache__/main.cpython-310.pyc differ diff --git a/monitoring/add-metrics/docker-compose.yml b/monitoring/add-metrics/docker-compose.yml new file mode 100644 index 00000000..40ea9ba0 --- /dev/null +++ b/monitoring/add-metrics/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + api: + build: + context: . + dockerfile: Dockerfile + container_name: jusan-monitoring-api + ports: + - "8000:8000" + volumes: + - .:/app + restart: always + + prometheus: + image: prom/prometheus:latest + container_name: prometheus + volumes: + - ./prometheus.yml:/etc/prometheus/prometheus.yml + ports: + - "9090:9090" + restart: always diff --git a/monitoring/add-metrics/main.py b/monitoring/add-metrics/main.py new file mode 100644 index 00000000..4a87fa8d --- /dev/null +++ b/monitoring/add-metrics/main.py @@ -0,0 +1,84 @@ +from fastapi import FastAPI, Request +from prometheus_client import Counter, Histogram, Gauge, make_asgi_app +import time + +# Инициализация приложения FastAPI +app = FastAPI() + +# Определение метрик +http_requests_total = Counter( + 'http_requests_total', 'Number of HTTP requests received', ['method', 'endpoint'] +) +http_requests_milliseconds = Histogram( + 'http_requests_milliseconds', 'Duration of HTTP requests in milliseconds', ['method', 'endpoint'] +) +last_sum1n = Gauge('last_sum1n', 'Value stores last result of sum1n') +last_fibo = Gauge('last_fibo', 'Value stores last result of fibo') +last_calculator = Gauge('last_calculator', 'Value stores last result of calculator') +errors_calculator_total = Counter( + 'errors_calculator_total', 'Number of errors in calculator' +) + +# Middleware для отслеживания запросов +@app.middleware("http") +async def metrics_middleware(request: Request, call_next): + start_time = time.time() + method = request.method + endpoint = request.url.path + http_requests_total.labels(method=method, endpoint=endpoint).inc() + + try: + response = await call_next(request) + except Exception as e: + if endpoint == "/calculator": + errors_calculator_total.inc() + raise e + finally: + duration = (time.time() - start_time) * 1000 + http_requests_milliseconds.labels(method=method, endpoint=endpoint).observe(duration) + + return response + +# Обработчики запросов +@app.get("/sum1n") +def sum1n(n: int): + result = sum(range(1, n + 1)) + last_sum1n.set(result) + return {"result": result} + +@app.get("/fibo") +def fibo(n: int): + def fibonacci(n): + if n <= 1: + return n + return fibonacci(n - 1) + fibonacci(n - 2) + + result = fibonacci(n) + last_fibo.set(result) + return {"result": result} + +@app.get("/calculator") +def calculator(operation: str, a: float, b: float): + try: + if operation == "add": + result = a + b + elif operation == "subtract": + result = a - b + elif operation == "multiply": + result = a * b + elif operation == "divide": + if b == 0: + raise ZeroDivisionError + result = a / b + else: + raise ValueError("Invalid operation") + last_calculator.set(result) + return {"result": result} + except (ValueError, ZeroDivisionError) as e: + errors_calculator_total.inc() + return {"error": str(e)} + +# Настройка Prometheus Exporter +from starlette.middleware import Middleware +metrics_app = make_asgi_app() +app.mount("/metrics", metrics_app) diff --git a/monitoring/add-metrics/prometheus.yml b/monitoring/add-metrics/prometheus.yml new file mode 100644 index 00000000..58754a42 --- /dev/null +++ b/monitoring/add-metrics/prometheus.yml @@ -0,0 +1,7 @@ +global: + scrape_interval: 15s + +scrape_configs: + - job_name: 'fastapi' + static_configs: + - targets: ['api:8000'] diff --git a/monitoring/add-metrics/requirements.txt b/monitoring/add-metrics/requirements.txt new file mode 100644 index 00000000..095fe901 --- /dev/null +++ b/monitoring/add-metrics/requirements.txt @@ -0,0 +1,3 @@ +fastapi +uvicorn +prometheus-client==0.16.0 diff --git "a/python/\320\273\320\265\320\263\320\272\320\270\320\265 \320\262\320\276\320\277\321\200\320\276\321\201\321\213/Readme.Md" "b/python/\320\273\320\265\320\263\320\272\320\270\320\265 \320\262\320\276\320\277\321\200\320\276\321\201\321\213/Readme.Md" index 77795c19..d63ff68d 100644 --- "a/python/\320\273\320\265\320\263\320\272\320\270\320\265 \320\262\320\276\320\277\321\200\320\276\321\201\321\213/Readme.Md" +++ "b/python/\320\273\320\265\320\263\320\272\320\270\320\265 \320\262\320\276\320\277\321\200\320\276\321\201\321\213/Readme.Md" @@ -9,6 +9,17 @@ Sample Input: Sample Output: 1 +ответ: +def int_cmp(a, b): + if a > b: + return 1 + elif a == b: + return 0 + else: + return -1 +a, b = map(int, input().split()) +print(int_cmp(a, b)) + ##max-of-three Дается три числа a, b и c. Вернуть максимальное число из них. Sample Input: @@ -16,20 +27,28 @@ Sample Input: Sample Output: 42 +ответ +def max_of_three(a, b, c): + return max(a, b, c) +a, b, c = map(int, input("Введите три числа через пробел: ").split()) +print(max_of_three(a, b, c)) #Циклы ##sqr-sum-1-n Вернуть сумму квадратов чисел от 1 до n включительно. Ограничения 1 <= n <= 10860 - - - Sample Input: 3 Sample Output: 14 +ответ +def sqr_sum(n): + return (n * (n + 1) * (2 * n + 1)) // 6 +n = int(input("Введите число n: ")) +print(sqr_sum(n)) + @@ -40,7 +59,13 @@ Sample Input: 0 4 Sample Output: 0 2 4 - + ответ + def print_even(a, b): + for i in range(a, b + 1): + if i % 2 == 0: + print(i, end=" ") +a, b = map(int, input().split()) +print_even(a, b) ##pow-a-b Вернуть число a в степени b. Используя цикл. @@ -51,7 +76,14 @@ Sample Input: 2 6 Sample Output: 64 - + ответ + def power(a, b): + result = 1 + for _ in range(b): + result *= a + return result +a, b = map(int, input().split()) +print(power(a, b)) ##calc-deposit @@ -68,6 +100,13 @@ Sample Input: Sample Output: 1050.0 +ответ +def calc_deposit(n, k, b): + for _ in range(n): + b += b * (k / 100) + return b +n, k, b = map(int, input().split()) +print(calc_deposit(n, k, b)) @@ -82,7 +121,13 @@ Sample Input: [1, 2, 3] Sample Output: 1 - + ответ + def min_array(arr): + if len(arr) == 0: + return 0 + return min(arr) +arr = [1, 2, 3] +print(min_array(arr)) ##range Реализовать функцию range, которая создает массив размером n, заполняет ячейки значениями от 1 до n и возвращает созданный массив. @@ -101,6 +146,11 @@ Sample Input: Sample Output: [1, 2, 3, 4, 5] +ответ +def range_array(n): + return [i for i in range(1, n + 1)] +n = int(input()) +print(range_array(n)) ##sum Реализовать функцию sum, которая возвращает сумму чисел массива. @@ -115,6 +165,11 @@ Sample Input: [1, 2, 3] Sample Output: 6 + ответ + def sum_array(arr): + return sum(arr) +arr = [1, 2, 3] +print(sum_array(arr)) ##sort Реализовать функцию sort, которая принимает массив array(int[]). Функция должна отсортировать массив по возрастанию. @@ -136,3 +191,15 @@ Sample Input: Sample Output: [1, 2, 3] +ответ +def selection_sort(arr): + n = len(arr) + for i in range(n): + min_idx = i + for j in range(i + 1, n): + if arr[j] < arr[min_idx]: + min_idx = j + arr[i], arr[min_idx] = arr[min_idx], arr[i] +arr = [7, 5, 9, 1, 4] +selection_sort(arr) +print(arr) diff --git "a/python/\321\201\320\273\320\276\320\266\320\275\321\213\320\265 \320\267\320\260\320\264\320\260\321\207\320\270/readme.md" "b/python/\321\201\320\273\320\276\320\266\320\275\321\213\320\265 \320\267\320\260\320\264\320\260\321\207\320\270/readme.md" index db4d7d9d..72a9da86 100644 --- "a/python/\321\201\320\273\320\276\320\266\320\275\321\213\320\265 \320\267\320\260\320\264\320\260\321\207\320\270/readme.md" +++ "b/python/\321\201\320\273\320\276\320\266\320\275\321\213\320\265 \320\267\320\260\320\264\320\260\321\207\320\270/readme.md" @@ -9,6 +9,13 @@ Sample Input: Sample Output: 15 +#ответ +def sum_1_n(n): + return n * (n + 1) // 2 + +# Пример использования +n = 5 +print(sum_1_n(n)) # Выведет 15 @@ -34,6 +41,18 @@ Sample Input: Sample Output: 1 +#ответ + +def count_leap_year(n): + count_div4 = (n - 1) // 4 + count_div100 = (n - 1) // 100 + count_div400 = (n - 1) // 400 + return count_div4 - count_div100 + count_div400 + +# Пример использования +n = 100 +print(count_leap_year(n)) # Выведет 24 + ##swap-bits  Реализуйте метод, который меняет местами первые 4 бита с остальными 4 и возвращает результат. @@ -47,6 +66,22 @@ Sample Input: Sample Output: 240 +#ответ +def swap_bits(a): + # Извлечение старших 4 битов + upper_bits = (a >> 4) & 0b1111 + # Извлечение младших 4 битов + lower_bits = a & 0b1111 + # Поменять местами и объединить + result = (lower_bits << 4) | upper_bits + return result + +# Пример использования +a = 15 +print(swap_bits(a)) # Выведет 240 + + + @@ -79,6 +114,24 @@ Sample Input: Sample Output: 2 +#ответ +def sort_nums_three(a, b, c): + # Сначала проверим, если a больше b, поменяем их местами + if a > b: + a, b = b, a + # Теперь если b больше c, поменяем их местами + if b > c: + b, c = c, b + # Повторно проверим a и b, потому что a могло быть больше c + if a > b: + a, b = b, a + print(a, b, c) + +# Пример использования +a, b, c = 3, 2, 1 +sort_nums_three(a, b, c) # Выведет 1 2 3 + + @@ -93,6 +146,21 @@ Sample Input: Sample Output: [7, 9] +#ответ +def miss_you(array1, array2): + # Преобразуем первый массив в множество для быстрого поиска + set1 = set(array1) + + # Находим элементы второго массива, которые не входят в первый массив + result = sorted(set(x for x in array2 if x not in set1)) + + return result + +# Пример использования +array1 = [1, 1, 3, 2, 5] +array2 = [1, 3, 9, 1, 5, 7] +print(miss_you(array1, array2)) # Выведет [7, 9] + ##perfectly-balanced  @@ -111,6 +179,34 @@ Sample Input: Sample Output: true +#ответ + +def perfectly_balanced(array): + # Считаем полную сумму всех элементов + total_sum = sum(array) + + # Инициализируем сумму элементов слева + left_sum = 0 + + # Проходим по каждому элементу массива + for i in range(len(array)): + # Вычитаем текущий элемент из правой суммы + right_sum = total_sum - left_sum - array[i] + + # Проверяем, равны ли суммы слева и справа + if left_sum == right_sum: + return True + + # Добавляем текущий элемент к левой сумме + left_sum += array[i] + + # Если мы прошли по всему массиву и не нашли, возвращаем False + return False + +# Пример использования +array = [1, 2, 9, 8, 5, 7] +print(perfectly_balanced(array)) # Выведет True + ##stock-buy  @@ -132,6 +228,27 @@ Sample Input: Sample Output: 0 1 +#ответ +def stock_buy(m, s): + # Создаем словарь для хранения индексов + seen = {} + + # Проходим по массиву + for i, price in enumerate(s): + # Вычисляем необходимую пару для текущего элемента + complement = m - price + + # Если пара найдена в словаре, возвращаем индексы + if complement in seen: + return sorted([seen[complement], i]) + + # Иначе сохраняем текущую цену и ее индекс в словарь + seen[price] = i + +# Пример использования +m = 8 +s = [8, 7, 3, 1, 3, 10] +print(stock_buy(m, s)) # Выведет [1, 3] @@ -194,3 +311,23 @@ Sample Output: Диск 2 с башни 2 переложить в башню 3 Диск 1 с башни 1 переложить в башню 3 +#ответ +def hanoiTower(n, from_tower=1, to_tower=3, aux_tower=2): + # Базовый случай: если один диск, перемещаем его напрямую + if n == 1: + print(f"Диск {n} с башни {from_tower} переложить в башню {to_tower}") + return + + # Шаг 1: Переместить n-1 дисков с from_tower на вспомогательную башню + hanoiTower(n - 1, from_tower, aux_tower, to_tower) + + # Шаг 2: Переместить самый большой диск с from_tower на to_tower + print(f"Диск {n} с башни {from_tower} переложить в башню {to_tower}") + + # Шаг 3: Переместить n-1 дисков с вспомогательной башни на to_tower + hanoiTower(n - 1, aux_tower, to_tower, from_tower) + +# Пример использования +n = 5 +hanoiTower(n) + diff --git "a/python/\321\201\321\200\320\265\320\264\320\275\320\270\320\265 \320\267\320\260\320\264\320\260\321\207\320\270/readme.md" "b/python/\321\201\321\200\320\265\320\264\320\275\320\270\320\265 \320\267\320\260\320\264\320\260\321\207\320\270/readme.md" index 6f1a3631..4ee04218 100644 --- "a/python/\321\201\321\200\320\265\320\264\320\275\320\270\320\265 \320\267\320\260\320\264\320\260\321\207\320\270/readme.md" +++ "b/python/\321\201\321\200\320\265\320\264\320\275\320\270\320\265 \320\267\320\260\320\264\320\260\321\207\320\270/readme.md" @@ -1,21 +1,153 @@ 1.Создайте программу, которая проверяет, является ли введенное пользователем число четным или нечетным, и выводит соответствующее сообщение. +# ответ + +# Запрашиваем у пользователя ввод числа +number = int(input("Введите число: ")) + +# Проверяем, является ли число четным или нечетным +if number % 2 == 0: + print(f"Число {number} является четным.") +else: + print(f"Число {number} является нечетным.") 2.Реализуйте программу, которая определяет, является ли введенная пользователем строка палиндромом (читается одинаково слева направо и справа налево). Выведите соответствующее сообщение. s +# ответ + +# Запрашиваем у пользователя ввод строки +s = input("Введите строку: ") + +# Удаляем пробелы и приводим строку к нижнему регистру +cleaned_s = s.replace(" ", "").lower() + +# Проверяем, является ли строка палиндромом +if cleaned_s == cleaned_s[::-1]: + print(f"Строка '{s}' является палиндромом.") +else: + print(f"Строка '{s}' не является палиндромом.") 3.Реализуйте программу, которая определяет, является ли заданное число простым (имеет только два делителя: 1 и само число). Выведите соответствующее сообщение. +# ответ +# Функция для проверки, является ли число простым +def is_prime(n): + if n <= 1: # Числа меньше или равные 1 не являются простыми + return False + for i in range(2, int(n**0.5) + 1): # Проверяем делители от 2 до √n + if n % i == 0: # Если n делится на i, то это не простое число + return False + return True # Если не нашли делителей, число простое + +# Запрашиваем у пользователя ввод числа +number = int(input("Введите число: ")) + +# Проверяем, является ли число простым +if is_prime(number): + print(f"Число {number} является простым.") +else: + print(f"Число {number} не является простым.") + 4.Реализуйте программу, которая определяет, является ли заданная дата корректной (). Выведите соответствующее сообщение. Дата дана в формате “20.01.2002” +# ответ +from datetime import datetime + +# Функция для проверки корректности даты +def is_valid_date(date_str): + try: + # Пробуем преобразовать строку в объект даты + datetime.strptime(date_str, "%d.%m.%Y") + return True # Если преобразование прошло успешно, дата корректная + except ValueError: + return False # Если возникла ошибка, дата некорректная + +# Запрашиваем у пользователя ввод даты +date_input = input("Введите дату в формате DD.MM.YYYY: ") + +# Проверяем, является ли дата корректной +if is_valid_date(date_input): + print(f"Дата '{date_input}' является корректной.") +else: + print(f"Дата '{date_input}' не является корректной.") 5.Напишите программу для нахождения всех совершенных чисел (чисел, равных сумме своих делителей, исключая само число) в заданном диапазоне. Диапазон от 0 до 1000 +# ответ +def is_perfect_number(n): + # Считаем сумму делителей числа n, исключая само число + sum_of_divisors = sum(i for i in range(1, n) if n % i == 0) + return sum_of_divisors == n # Проверяем, является ли n совершенным + +# Находим все совершенные числа в диапазоне от 0 до 1000 +perfect_numbers = [num for num in range(1, 1001) if is_perfect_number(num)] + +# Выводим результат +print("Совершенные числа в диапазоне от 0 до 1000:", perfect_numbers) + 6.Реализуйте программу для проверки, является ли заданное число числом Фибоначчи (число, которое является членом последовательности Фибоначчи). Заданное число 25 +# ответ +def is_fibonacci(n): + # Начальные значения последовательности Фибоначчи + a, b = 0, 1 + while a < n: + a, b = b, a + b # Генерируем следующее число Фибоначчи + return a == n # Проверяем, является ли n числом Фибоначчи + +# Заданное число +number = 25 + +# Проверяем, является ли число Фибоначчи +if is_fibonacci(number): + print(f"Число {number} является числом Фибоначчи.") +else: + print(f"Число {number} не является числом Фибоначчи.") + 7.Напишите программу, которая определяет, является ли заданное число совершенным числом (число, равное сумме своих делителей, исключая само число). Выведите сообщение с результатом. +# ответ +def is_perfect_number(n): + if n <= 1: + return False # Числа 0 и 1 не являются совершенными + # Считаем сумму делителей числа n, исключая само число + sum_of_divisors = sum(i for i in range(1, n) if n % i == 0) + return sum_of_divisors == n # Проверяем, является ли n совершенным + +# Заданное число +number = int(input("Введите число: ")) + +# Проверяем, является ли число совершенным +if is_perfect_number(number): + print(f"Число {number} является совершенным.") +else: + print(f"Число {number} не является совершенным.") + +8.Создайте программу, которая определяет, в какой сезон года попадает заданная дата (месяц и день). +# ответ +def determine_season(month, day): + # Определяем сезоны по месяцам и дням + if (month == 12 and day >= 21) or (month <= 2) or (month == 3 and day < 20): + return "Зима" + elif (month == 3 and day >= 20) or (month <= 5) or (month == 6 and day < 21): + return "Весна" + elif (month == 6 and day >= 21) or (month <= 8) or (month == 9 and day < 23): + return "Лето" + elif (month == 9 and day >= 23) or (month <= 11) or (month == 12 and day < 21): + return "Осень" + else: + return "Некорректная дата" # Для некорректных значений + +# Запрашиваем у пользователя ввод месяца и дня +month = int(input("Введите месяц (1-12): ")) +day = int(input("Введите день (1-31): ")) -8.Создайте программу, которая определяет, в какой сезон года попадает заданная дата (месяц и день). \ No newline at end of file +# Проверяем корректность введенной даты (не идеально, но для простоты) +if (month < 1 or month > 12) or (day < 1 or day > 31): + print("Некорректная дата") +else: + # Определяем сезон + season = determine_season(month, day) + print(f"Дата {day}.{month} попадает в сезон: {season}.")